From 72c1ccba963a3f09ae7b6e05cee9e72b674fbe4e Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Sat, 7 Jan 2017 01:17:47 +0300 Subject: [PATCH] charts: make clip-data handle y coords as well Implementation is efficient: the minmax for y is only called after trimming the data on the x bounds. If the entire data set is outside the x range, handling is terminated early. --- charts-tests.factor | 8 +++++++- charts.factor | 48 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/charts-tests.factor b/charts-tests.factor index 49bcdaa199..67c6444e8b 100644 --- a/charts-tests.factor +++ b/charts-tests.factor @@ -3,6 +3,12 @@ USING: tools.test charts ; IN: charts.tests +{ { } } +[ { } { } clip-data ] unit-test + +{ { } } +[ { { 0 1 } { 0 5 } } { } clip-data ] unit-test + ! Adjustment after search is required in both directions. { { @@ -11,7 +17,7 @@ IN: charts.tests { 5 9 } { 5 10 } { 5 11 } { 5 12 } } } [ - { 1 5 } + { { 1 5 } { 0 14 } } { { 0 1 } { 0 2 } { 1 3 } { 1 4 } { 1 5 } diff --git a/charts.factor b/charts.factor index e8fc499c6b..b643ca1f70 100644 --- a/charts.factor +++ b/charts.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2016-2017 Alexander Ilin. -USING: accessors binary-search colors.constants kernel locals -math math.order opengl opengl.gl sequences +USING: accessors arrays binary-search colors.constants +combinators.short-circuit kernel locals math math.order +math.rectangles math.statistics opengl opengl.gl sequences specialized-arrays.instances.alien.c-types.float ui.gadgets ui.render ; IN: charts @@ -36,21 +37,50 @@ M: chart pref-dim* drop { 300 300 } ; : adjusted-head ( index elt seq -- seq' ) [ finder find-from drop ] keep swap [ head ] when* ; -:: in-bounds? ( bounds data -- ? ) - bounds first data last first < not - bounds second data first first > not - and ; +! : data-rect ( data -- rect ) +! [ [ first first ] [ last first ] bi ] keep +! [ second ] map minmax swapd +! 2array [ 2array ] dip ; -PRIVATE> +: first-in-bounds? ( min,max pairs -- ? ) + { + [ [ first ] dip last first > not ] + [ [ second ] dip first first < not ] + } 2&& ; -: clip-data ( bounds data -- data' ) - 2dup in-bounds? [ +: second-in-bounds? ( min,max pairs -- ? ) + [ second ] map minmax 2array + { + [ [ first ] dip second > not ] + [ [ second ] dip first < not ] + } 2&& ; + +! : pairs-in-bounds? ( bounds pairs -- ? ) +! { +! [ [ first ] dip first-in-bounds? ] +! [ [ second ] dip second-in-bounds? ] +! } 2&& ; + +: clip-by-first ( min,max pairs -- pairs' ) + 2dup first-in-bounds? [ [ dup first ] dip [ search-index ] keep adjusted-tail [ second ] dip [ search-index ] keep adjusted-head ] [ 2drop { } clone ] if ; +PRIVATE> + +! bounds: { { first-min first-max } { second-min second-max } } +: clip-data ( bounds data -- data' ) + dup empty? [ nip ] [ + dupd [ first ] dip clip-by-first + dup empty? [ nip ] [ + [ second ] dip [ second-in-bounds? ] keep swap + [ drop { } clone ] unless + ] if + ] if ; + ! Return the bottom-left and top-right corners of the visible area. : chart-axes ( chart -- seq ) drop { { 0 300 } { 300 0 } } ;