src/JsPlot3D.js
/**
     * repeats the drawing using the dataframe memorized in oldData, but adds a new datapoint to it
     * @param {any} newDatapoint Array that contains the attributes of the datapoints in terms of x1, x2, x3, x4, x5 etc.
     * - for example [100,100,100,100,"rock"]
     * @param {object} options json object with one or more of the following parameters:
     * - mode {string}: "barchart", "scatterplot" or "lineplot"
     * - colorCol {number}: leave undefined or set to -1, if defaultColor should be applied. Otherwise the index of the csv column that contains color information.
     * (0, 1, 2 etc.). Formats of the column within the .csv file allowed:
     * numbers (normalized automatically, range doesn't matter). Numbers are converted to a heatmap automatically.
     * Integers that are used as class for labeled data would result in various different hues in the same way.
     * hex strings ("#f8e2b9"). "rgb(...)" strings. "hsl(...)" strings. strings as labels (make sure to set labeled = true).
     * - normalizeX1 {boolean}: if false, data will not be normalized. Datapoints with high values will be very far away then on the X1 Axis
     * - normalizeX2 {boolean}: if false, data will not be normalized. Datapoints with high values will be very far away then on the X2 Axis (y)
     * - normalizeX3 {boolean}: if false, data will not be normalized. Datapoints with high values will be very far away then on the X3 Axis
     * - title {string}: title of the data
     * - fraction {number}: between 0 and 1, how much of the dataset should be plotted.
     * - labeled {boolean}: true if colorCol contains labels (such as 0, 1, 2 or frog, cat, dog). This changes the way it is colored.
     * Having it false on string-labeled data will throw a warning, but it will continue as it was true
     * - defaultColor {number or string}: examples: #1a3b5c, 0xfe629a, rgb(0.1,0.2,0.3), hsl(0.4,0.5,0.6). Gets applied when either colorCol is -1, undefined or ""
     * - x1frac {number}: by how much to divide the datapoints x1 value to fit into [-1;1]. will be overwritten if normalization is on
     * - x2frac {number}: by how much to divide the datapoints x2 value (y) to fit into [-1;1]. will be overwritten if normalization is on
     * - x3frac {number}: by how much to divide the datapoints x3 value to fit into [-1;1]. will be overwritten if normalization is on
     * - barchartPadding {number}: how much space should there be between the bars? Example: 0.025
     * - dataPointSize {number}: how large the datapoint should be. Default: 0.04
     * - filterColor {boolean}: false: if the column with the index of the parameter "colorCol" contains numbers they are going to be treated
     * as if it was a color. (converted to hexadecimal then and not filtered to a heatmap). Default true, which filters it to a heatmap
     * - x1title {string}: title of the x1 axis
     * - x2title {string}: title of the x2 axis
     * - x3title {string}: title of the x3 axis
     * - hueOffset {number}: how much to rotate the hue of the labels. between 0 and 1. Default: 0
     * - keepOldPlot {boolean}: don't remove the old datapoints/bars/etc. when this is true
     * - barSizeThreshold {number}: smallest allowed y value for the bars. Smaller than that will be hidden. Between 0 and 1. 1 Hides all bars, 0 shows all. Default 0
     * - numberDensity {number}: how many numbers to display when the length (xLen, yLen or zLen) equals 1. A smaller axis displays fewer numbers and a larger axis displays more.
     */
repeats the drawing using the dataframe memorized in oldData, but adds a new datapoint to it
@param {any} newDatapoint Array that contains the attributes of the datapoints in terms of x1, x2, x3, x4, x5 etc.
repeats the drawing using the dataframe memorized in oldData but adds a new datapoint to it @param { any } newDatapoint Array that contains the attributes of the datapoints in terms of x1 x2 x3 x4 x5 etc .
addDataPoint(newDatapoint, options={})
    {            
        if(this.oldData.options.mode == POLYGON_MODE)
        {
            return console.error("the current plot is a",POLYGON_MODE,"which is only the case for formulas. You can't add datapoints to formulas")
        }
        for(let key in this.oldData.options)
        {
            if(options[key] === undefined)
            {
                options[key] = this.oldData.options[key]
            }
        }
        options.header = false
        options.updateOldData = false
        if(this.isAnimated())
            options.fastForward = true 
        if(options.normalizeX1 === undefined) options.normalizeX1 = false
        if(options.normalizeX2 === undefined) options.normalizeX2 = false
        if(options.normalizeX3 === undefined) options.normalizeX3 = false
        if(options.keepOldPlot === undefined) options.keepOldPlot = true
        if(typeof(newDatapoint) === "string")
        {
            newDatapoint = newDatapoint.split(options.separator)
            for(let i = 0;i < newDatapoint.length; i++)
                newDatapoint[i] = newDatapoint[i].trim()
        }
        this.oldData.dataframe[this.oldData.dataframe.length] = newDatapoint
        if(newDatapoint.length != this.oldData.dataframe[0].length)
        {
            return console.error("the new datapoint does not match the number of column in the in oldData stored dataframe ("+newDatapoint.length+" != "+this.oldData.dataframe[0].length+")")
        }
        this.plotDataFrame([newDatapoint],
            this.oldData.x1col,
            this.oldData.x2col,
            this.oldData.x3col,
            options
        )
        this.oldData.checkstring += "_addDP"
    }
addDataPoint ( newDatapoint , options = { } ) { if ( this . oldData . options . mode == POLYGON_MODE ) { return console . error ( "the current plot is a" , POLYGON_MODE , "which is only the case for formulas. You can't add datapoints to formulas" ) } for ( let key in this . oldData . options ) { if ( options [ key ] === undefined ) { options [ key ] = this . oldData . options [ key ] } } options . header = false options . updateOldData = false if ( this . isAnimated ( ) ) options . fastForward = true if ( options . normalizeX1 === undefined ) options . normalizeX1 = false if ( options . normalizeX2 === undefined ) options . normalizeX2 = false if ( options . normalizeX3 === undefined ) options . normalizeX3 = false if ( options . keepOldPlot === undefined ) options . keepOldPlot = true if ( typeof ( newDatapoint ) === "string" ) { newDatapoint = newDatapoint . split ( options . separator ) for ( let i = 0 ; i < newDatapoint . length ; i ++ ) newDatapoint [ i ] = newDatapoint [ i ] . trim ( ) } this . oldData . dataframe [ this . oldData . dataframe . length ] = newDatapoint if ( newDatapoint . length != this . oldData . dataframe [ 0 ] . length ) { return console . error ( "the new datapoint does not match the number of column in the in oldData stored dataframe (" + newDatapoint . length + " != " + this . oldData . dataframe [ 0 ] . length + ")" ) } this . plotDataFrame ( [ newDatapoint ] , this . oldData . x1col , this . oldData . x2col , this . oldData . x3col , options ) this . oldData . checkstring += "_addDP" }
repeats the drawing using the dataframe memorized in oldData, but adds a new datapoint to it
 @param {any} newDatapoint Array that contains the attributes of the datapoints in terms of x1, x2, x3, x4, x5 etc.
repeats the drawing using the dataframe memorized in oldData but adds a new datapoint to it @param { any } newDatapoint Array that contains the attributes of the datapoints in terms of x1 x2 x3 x4 x5 etc .
// is the plot a formula? // to avoid destroying the plot, return here // add the old options to the current options // the following have to be like this, they can't be overwritten by the user: // no header in newDataPoint and don't delete the original dataframe from cache // performance // default keepOldPlot, but make it possible to overwrite it. // true by default, so that the old plot gets extended with the new datapoint. // Set to false to replace the old plot with this new single datapoint // check for undefined, it is a boolean value! don't if(!foobar) // create the datapoint data structure (an array) from this // add the datapoint to the dataframe // because of keepOldPlot, only hand the newDatapoint over to plotDataFrame // destroy the in oldData stored string csv checkstring, indicate that the dataframe has been modified by addDataPoint // do this, because otherwise when plotting the same (initial) dataframe again it might not realize that the in oldData stored dataframe has // been extended by addDataPoint, so plotCsvString might use the in oldData stored (longer) dataframe than the one passed as parameter