@@ -19,11 +19,10 @@ var findAllPaths = require('../contour/find_all_paths');
1919var contourPlot = require ( '../contour/plot' ) ;
2020var constants = require ( '../contour/constants' ) ;
2121var convertToConstraints = require ( '../contour/convert_to_constraints' ) ;
22- var joinAllPaths = require ( './join_all_paths' ) ;
2322var emptyPathinfo = require ( '../contour/empty_pathinfo' ) ;
24- var mapPathinfo = require ( './map_pathinfo' ) ;
25- var lookupCarpet = require ( '../carpet/lookup_carpetid' ) ;
2623var closeBoundaries = require ( '../contour/close_boundaries' ) ;
24+ var lookupCarpet = require ( '../carpet/lookup_carpetid' ) ;
25+ var axisAlignedLine = require ( '../carpet/axis_aligned_line' ) ;
2726
2827module . exports = function plot ( gd , plotinfo , cdcontours , contourcarpetLayer ) {
2928 var xa = plotinfo . xaxis ;
@@ -117,6 +116,32 @@ module.exports = function plot(gd, plotinfo, cdcontours, contourcarpetLayer) {
117116 } ) ;
118117} ;
119118
119+ function mapPathinfo ( pathinfo , map ) {
120+ var i , j , k , pi , pedgepaths , ppaths , pedgepath , ppath , path ;
121+
122+ for ( i = 0 ; i < pathinfo . length ; i ++ ) {
123+ pi = pathinfo [ i ] ;
124+ pedgepaths = pi . pedgepaths = [ ] ;
125+ ppaths = pi . ppaths = [ ] ;
126+ for ( j = 0 ; j < pi . edgepaths . length ; j ++ ) {
127+ path = pi . edgepaths [ j ] ;
128+ pedgepath = [ ] ;
129+ for ( k = 0 ; k < path . length ; k ++ ) {
130+ pedgepath [ k ] = map ( path [ k ] ) ;
131+ }
132+ pedgepaths . push ( pedgepath ) ;
133+ }
134+ for ( j = 0 ; j < pi . paths . length ; j ++ ) {
135+ path = pi . paths [ j ] ;
136+ ppath = [ ] ;
137+ for ( k = 0 ; k < path . length ; k ++ ) {
138+ ppath [ k ] = map ( path [ k ] ) ;
139+ }
140+ ppaths . push ( ppath ) ;
141+ }
142+ }
143+ }
144+
120145function makeLinesAndLabels ( plotgroup , pathinfo , gd , cd0 , contours , plotinfo , carpet ) {
121146 var lineContainer = Lib . ensureSingle ( plotgroup , 'g' , 'contourlines' ) ;
122147 var showLines = contours . showlines !== false ;
@@ -330,3 +355,124 @@ function makeFills(trace, plotgroup, xa, ya, pathinfo, perimeter, ab2p, carpet,
330355 }
331356 } ) ;
332357}
358+
359+ function joinAllPaths ( trace , pi , perimeter , ab2p , carpet , carpetcd , xa , ya ) {
360+ var i ;
361+ var fullpath = '' ;
362+
363+ var startsleft = pi . edgepaths . map ( function ( v , i ) { return i ; } ) ;
364+ var newloop = true ;
365+ var endpt , newendpt , cnt , nexti , possiblei , addpath ;
366+
367+ var atol = Math . abs ( perimeter [ 0 ] [ 0 ] - perimeter [ 2 ] [ 0 ] ) * 1e-4 ;
368+ var btol = Math . abs ( perimeter [ 0 ] [ 1 ] - perimeter [ 2 ] [ 1 ] ) * 1e-4 ;
369+
370+ function istop ( pt ) { return Math . abs ( pt [ 1 ] - perimeter [ 0 ] [ 1 ] ) < btol ; }
371+ function isbottom ( pt ) { return Math . abs ( pt [ 1 ] - perimeter [ 2 ] [ 1 ] ) < btol ; }
372+ function isleft ( pt ) { return Math . abs ( pt [ 0 ] - perimeter [ 0 ] [ 0 ] ) < atol ; }
373+ function isright ( pt ) { return Math . abs ( pt [ 0 ] - perimeter [ 2 ] [ 0 ] ) < atol ; }
374+
375+ function pathto ( pt0 , pt1 ) {
376+ var i , j , segments , axis ;
377+ var path = '' ;
378+
379+ if ( ( istop ( pt0 ) && ! isright ( pt0 ) ) || ( isbottom ( pt0 ) && ! isleft ( pt0 ) ) ) {
380+ axis = carpet . aaxis ;
381+ segments = axisAlignedLine ( carpet , carpetcd , [ pt0 [ 0 ] , pt1 [ 0 ] ] , 0.5 * ( pt0 [ 1 ] + pt1 [ 1 ] ) ) ;
382+ } else {
383+ axis = carpet . baxis ;
384+ segments = axisAlignedLine ( carpet , carpetcd , 0.5 * ( pt0 [ 0 ] + pt1 [ 0 ] ) , [ pt0 [ 1 ] , pt1 [ 1 ] ] ) ;
385+ }
386+
387+ for ( i = 1 ; i < segments . length ; i ++ ) {
388+ path += axis . smoothing ? 'C' : 'L' ;
389+ for ( j = 0 ; j < segments [ i ] . length ; j ++ ) {
390+ var pt = segments [ i ] [ j ] ;
391+ path += [ xa . c2p ( pt [ 0 ] ) , ya . c2p ( pt [ 1 ] ) ] + ' ' ;
392+ }
393+ }
394+
395+ return path ;
396+ }
397+
398+ i = 0 ;
399+ endpt = null ;
400+ while ( startsleft . length ) {
401+ var startpt = pi . edgepaths [ i ] [ 0 ] ;
402+
403+ if ( endpt ) {
404+ fullpath += pathto ( endpt , startpt ) ;
405+ }
406+
407+ addpath = Drawing . smoothopen ( pi . edgepaths [ i ] . map ( ab2p ) , pi . smoothing ) ;
408+ fullpath += newloop ? addpath : addpath . replace ( / ^ M / , 'L' ) ;
409+ startsleft . splice ( startsleft . indexOf ( i ) , 1 ) ;
410+ endpt = pi . edgepaths [ i ] [ pi . edgepaths [ i ] . length - 1 ] ;
411+ nexti = - 1 ;
412+
413+ // now loop through sides, moving our endpoint until we find a new start
414+ for ( cnt = 0 ; cnt < 4 ; cnt ++ ) { // just to prevent infinite loops
415+ if ( ! endpt ) {
416+ Lib . log ( 'Missing end?' , i , pi ) ;
417+ break ;
418+ }
419+
420+ if ( istop ( endpt ) && ! isright ( endpt ) ) {
421+ newendpt = perimeter [ 1 ] ; // left top ---> right top
422+ } else if ( isleft ( endpt ) ) {
423+ newendpt = perimeter [ 0 ] ; // left bottom ---> left top
424+ } else if ( isbottom ( endpt ) ) {
425+ newendpt = perimeter [ 3 ] ; // right bottom
426+ } else if ( isright ( endpt ) ) {
427+ newendpt = perimeter [ 2 ] ; // left bottom
428+ }
429+
430+ for ( possiblei = 0 ; possiblei < pi . edgepaths . length ; possiblei ++ ) {
431+ var ptNew = pi . edgepaths [ possiblei ] [ 0 ] ;
432+ // is ptNew on the (horz. or vert.) segment from endpt to newendpt?
433+ if ( Math . abs ( endpt [ 0 ] - newendpt [ 0 ] ) < atol ) {
434+ if ( Math . abs ( endpt [ 0 ] - ptNew [ 0 ] ) < atol &&
435+ ( ptNew [ 1 ] - endpt [ 1 ] ) * ( newendpt [ 1 ] - ptNew [ 1 ] ) >= 0 ) {
436+ newendpt = ptNew ;
437+ nexti = possiblei ;
438+ }
439+ } else if ( Math . abs ( endpt [ 1 ] - newendpt [ 1 ] ) < btol ) {
440+ if ( Math . abs ( endpt [ 1 ] - ptNew [ 1 ] ) < btol &&
441+ ( ptNew [ 0 ] - endpt [ 0 ] ) * ( newendpt [ 0 ] - ptNew [ 0 ] ) >= 0 ) {
442+ newendpt = ptNew ;
443+ nexti = possiblei ;
444+ }
445+ } else {
446+ Lib . log ( 'endpt to newendpt is not vert. or horz.' , endpt , newendpt , ptNew ) ;
447+ }
448+ }
449+
450+ if ( nexti >= 0 ) break ;
451+ fullpath += pathto ( endpt , newendpt ) ;
452+ endpt = newendpt ;
453+ }
454+
455+ if ( nexti === pi . edgepaths . length ) {
456+ Lib . log ( 'unclosed perimeter path' ) ;
457+ break ;
458+ }
459+
460+ i = nexti ;
461+
462+ // if we closed back on a loop we already included,
463+ // close it and start a new loop
464+ newloop = ( startsleft . indexOf ( i ) === - 1 ) ;
465+ if ( newloop ) {
466+ i = startsleft [ 0 ] ;
467+ fullpath += pathto ( endpt , newendpt ) + 'Z' ;
468+ endpt = null ;
469+ }
470+ }
471+
472+ // finally add the interior paths
473+ for ( i = 0 ; i < pi . paths . length ; i ++ ) {
474+ fullpath += Drawing . smoothclosed ( pi . paths [ i ] . map ( ab2p ) , pi . smoothing ) ;
475+ }
476+
477+ return fullpath ;
478+ }
0 commit comments