Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Tagged as

JavaScript Machine Learning and Neural Networks with Encog

, 16 Oct 2012 Apache
Use Encog genetic algorithms, simulated annealing, neural networks and more with HTML5 Javascript.
heaton-javascript-ml.zip
encog-encog-javascript-6da0a8b
EncogJavascript.iml
EncogJavascript.ipr
README
encog.ipr
examples
/*
 * Encog(tm) Core v0.1 - Javascript Version
 * http://www.heatonresearch.com/encog/
 * http://code.google.com/p/encog-java/

 * Copyright 2008-2012 Heaton Research, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *   
 * For more information on Heaton Research copyrights, licenses 
 * and trademarks visit:
 * http://www.heatonresearch.com/copyright
 */

ENCOG.namespace('ENCOG.GUI.Console');
ENCOG.namespace('ENCOG.GUI.CellGrid');
ENCOG.namespace('ENCOG.GUI.Drawing');
ENCOG.namespace('ENCOG.GUI.Agents2D');
ENCOG.namespace('ENCOG.GUI.TSP');

ENCOG.GUI.Console = function () {
    'use strict'
};

ENCOG.GUI.Console.prototype =
{
    consoleDiv:{},
    textarea:{},
    name:"Console",
    write:function (str) {
        'use strict';
        this.textarea.value += (str);
        this.textarea.scrollTop = this.textarea.scrollHeight;
    },
    writeLine:function (str) {
        'use strict';
        this.textarea.value += (str + '\n');
        this.textarea.scrollTop = this.textarea.scrollHeight;
    },
    clear:function () {
        'use strict';
        this.textarea.value = "";
    }
};

ENCOG.GUI.Console.create = function (id) {
    'use strict';
    var result = new ENCOG.GUI.Console();
    result.consoleDiv = document.getElementById(id);
    result.consoleDiv.innerHTML = '<textarea></textarea>';
    result.textarea = result.consoleDiv.getElementsByTagName('textarea')[0];
    return result;
};

ENCOG.GUI.CellGrid = function () {
    'use strict'
};

ENCOG.GUI.CellGrid.prototype =
{
    canvas:null,
    drawingContext:null,
    canvasDiv:null,
    canvasWidth:null,
    canvasHeight:null,
    gridWidth:null,
    gridHeight:null,
    determineColor:null,
    pointerDown:null,
    pointerUp:null,
    pointerMove:null,
    pointerMode:0,
    captureTouch:true,
    outline:false,
    NAME:"CellGrid",

    render:function () {
        var output, row, col, r, g, b, c;

        this.drawingContext.strokeStyle = 'grey';

        for (row = 0; row < this.gridHeight; row += 1) {
            for (col = 0; col < this.gridWidth; col += 1) {
                this.drawingContext.fillStyle = this.determineColor(row, col);
                this.drawingContext.fillRect(col * this.pixW, row * this.pixH, this.pixW, this.pixH);
                if (this.outline) {
                    this.drawingContext.strokeRect(col * this.pixW, row * this.pixH, this.pixW, this.pixW);
                }
            }
        }

        this.drawingContext.strokeStyle = "black";
    },
    ev_canvas:function (ev) {

        var row, col;

        if (ev.layerX || ev.layerX == 0) {
            ev._x = ev.layerX;
            ev._y = ev.layerY;
        }
        // Opera
        else if (ev.offsetX || ev.offsetX == 0) {
            ev._x = ev.offsetX;
            ev._y = ev.offsetY;
        }

        switch (this.pointerMode) {
            case ENCOG.GUI.CellGrid.MODE_XY:
                row = ev._y;
                col = ev._x;
                break;
            case ENCOG.GUI.CellGrid.MODE_CELL:
                row = Math.floor(ev._y / this.pixH);
                col = Math.floor(ev._x / this.pixW);
                break;
            case ENCOG.GUI.CellGrid.MODE_PCT:
                row = ev._y / this.canvas.height;
                col = ev._x / this.canvas.width;
                break;
        }

        if (ev.type == 'mousedown' || ev.type == 'touchstart') {
            if (this.pointerDown != null) {
                this.pointerDown(row, col);
            }
        }
        else if (ev.type == 'mouseup' || ev.type == 'touchend') {
            if (this.pointerUp != null) {
                this.pointerUp(row, col);
            }
        }
        else if (ev.type == 'mousemove' || ev.type == 'touchmove') {
            if (this.pointerMove != null) {
                this.pointerMove(row, col);
            }
            if (this.captureTouch && ev.type == 'touchmove') {
                ev.preventDefault();
            }
        }
    },
    clear:function () {
        this.canvas.width = this.canvas.width;
    }
};

ENCOG.GUI.CellGrid.MODE_XY = 0;
ENCOG.GUI.CellGrid.MODE_CELL = 1;
ENCOG.GUI.CellGrid.MODE_PCT = 2;

ENCOG.GUI.CellGrid.create = function (id, gridWidth, gridHeight, canvasWidth, canvasHeight) {
    'use strict';
    var result = new ENCOG.GUI.CellGrid();
    result.canvasDiv = document.getElementById(id);
    result.canvasWidth = canvasWidth;
    result.canvasHeight = canvasHeight;
    result.gridWidth = gridWidth;
    result.gridHeight = gridHeight;
    result.canvasDiv.innerHTML = '<canvas width="'
        + canvasWidth + '" height="' + canvasHeight + '">Browser not supported.</canvas>';
    result.canvas = result.canvasDiv.getElementsByTagName('canvas')[0];
    result.drawingContext = result.canvas.getContext('2d');
    result.pixW = Math.floor(result.canvas.width / result.gridWidth);
    result.pixH = Math.floor(result.canvas.height / result.gridHeight);

    result.canvas.addEventListener('mousedown', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('mousemove', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('mouseup', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('touchstart', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('touchend', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('touchmove', function (e) {
        result.ev_canvas(e);
    }, true);
    result.canvas.addEventListener('mouseout', function (e) {
        result.ev_canvas(e);
    }, true);
    return result;
};


ENCOG.GUI.Drawing = function () {
    'use strict'
};

ENCOG.GUI.Drawing.create = function (id, canvasWidth, canvasHeight) {
    'use strict';
    var result = new ENCOG.GUI.Drawing();

    result.canvasDiv = document.getElementById(id);
    result.canvasWidth = canvasWidth;
    result.canvasHeight = canvasHeight;
    result.canvasDiv.innerHTML = '<canvas width="'
        + canvasWidth + '" height="' + canvasHeight + '">Browser not supported.</canvas>';
    result.canvas = result.canvasDiv.getElementsByTagName('canvas')[0];
    result.drawingContext = result.canvas.getContext('2d');

    // Attach the mousedown, mousemove and mouseup event listeners.
    result.canvas.addEventListener('mousedown', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mousemove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseup', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchstart', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchend', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchmove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseout', function (e) {
        result.ev_canvas(e)
    }, true);


    return result;
};

ENCOG.GUI.Drawing.prototype =
{
    canvas:null,
    drawingContext:null,
    canvasDiv:null,
    NAME:"Drawing",
    canvasWidth:null,
    canvasHeight:null,
    started:false,
    downsampleHeight:8,
    downsampleWidth:5,


    // Handle events to the canvas.  This allows drawing to occur.
    ev_canvas:function (ev) {
        // Firefox
        if (ev.layerX || ev.layerX == 0) {
            ev._x = ev.layerX;
            ev._y = ev.layerY;
        }
        // Opera
        else if (ev.offsetX || ev.offsetX == 0) {
            ev._x = ev.offsetX;
            ev._y = ev.offsetY;
        }

// This is called when you start holding down the mouse button.
// This starts the pencil drawing.
        if (ev.type === 'mousedown') {
            this.drawingContext.beginPath();
            this.drawingContext.moveTo(ev._x, ev._y);
            this.started = true;
        }

// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button).
        else if (ev.type === 'mousemove') {
            if (this.started) {
                this.drawingContext.lineTo(ev._x, ev._y);
                this.drawingContext.stroke();
            }
        }

// This is called when you release the mouse button.
        else if (ev.type === 'mouseup') {
            if (this.started) {
                this.drawingContext.lineTo(ev._x, ev._y);
                this.drawingContext.stroke();
                this.started = false;
            }
        }
        else if (ev.type === 'mouseout') {
            if (this.started) {
                this.drawingContext.lineTo(ev._x, ev._y);
                this.drawingContext.stroke();
                this.started = false;
            }
        }
        else if (ev.type === 'touchstart') {
            this.drawingContext.beginPath();
            this.drawingContext.moveTo(ev._x, ev._y);
            this.started = true;
        }
        else if (ev.type === 'touchend') {
            if (this.started) {
                this.started = false;
            }
        }
        else if (ev.type === 'touchmove') {
            if (this.started) {
                this.drawingContext.lineTo(ev._x, ev._y);
                this.drawingContext.stroke();
                ev.preventDefault();
            }
        }
    },
    // Determine if the specificed horizontal line is clear.
    // This is used to find the top and bottom cropping lines.
    isHLineClear:function (row) {
        var imgd = this.drawingContext.getImageData(0, row, this.canvas.width, 1);
        var pix = imgd.data;

        for (var i = 0; i < pix.length; i++) {
            if (pix[i] > 0) {
                return false;
            }
        }

        return true;
    },

// Determine if the specificed vertical line is clear.
// This is used to find the left and right cropping lines.
    isVLineClear:function (col) {
        var imgd = this.drawingContext.getImageData(col, 0, 1, this.canvas.height);
        var pix = imgd.data;

        for (var i = 0; i < pix.length; i++) {
            if (pix[i] > 0) {
                return false;
            }
        }

        return true;
    },

// Downsample the drawing area.
    performDownSample:function () {
        'use strict';
        var top, bottom, left, right, cellWidth, cellHeight, result, resultIndex, row, col, pix, x, y, d, i, imgd;

        // first find a bounding rectangle so that we can crop out unused space
        top = 0;

        while (this.isHLineClear(top) && top < this.canvas.height) {
            top++;
        }

        bottom = this.canvas.height;

        while (this.isHLineClear(bottom) && bottom > 0) {
            bottom--;
        }

        left = 0;

        while (this.isVLineClear(left) && left < this.canvas.width) {
            left++;
        }

        right = this.canvas.width;

        while (this.isVLineClear(right) && right > 0) {
            right--;
        }

        if (bottom < top) {
            result = ENCOG.ArrayUtil.allocate1D(this.downsampleHeight * this.downsampleWidth);
            ENCOG.ArrayUtil.fillArray(result, 0, result.length, -1);
            return result;
        }
        //uncomment this if you want to see the cropping rectangle
        //drawingContext.strokeRect(left,top,right-left,bottom-top);

        // now downsample

        cellWidth = (right - left) / this.downsampleWidth;
        cellHeight = (bottom - top) / this.downsampleHeight;
        result = new Array();
        resultIndex = 0;

        // to downsample we are going to lay a "grid" over the drawing
        // the grid's dimensions are defined by DOWNSAMPLE_HEIGHT and
        // DOWNSAMPLE_WIDTH.  Typically 5x8.  If even one pixel is
        // present in a grid square, it is downsampled to "black".

        for (row = 0; row < this.downsampleHeight; row++) {
            for (col = 0; col < this.downsampleWidth; col++) {
                x = (cellWidth * col) + left;
                y = (cellHeight * row) + top;

                // obtain pixel data for the grid square
                imgd = this.drawingContext.getImageData(x, y, cellWidth, cellHeight);
                pix = imgd.data;

                d = false;
                // see if at least one pixel is "black"
                for (i = 0; i < pix.length; i++) {
                    if (pix[i] > 0) {
                        d = true;
                        break;
                    }
                }

                // we are downsampling to an array where 1.0 is black, and -1.0 is white.
                // this will be used for Euclidean distance measuring.
                if (d) {
                    result[resultIndex++] = 1.0;
                } else {
                    result[resultIndex++] = -1.0;
                }
            }
        }

        return result;
    },
    clear:function () {
        this.canvas.width = this.canvas.width;
    }
};


////////////////////////////////////

ENCOG.GUI.Agents2D = function () {
    'use strict'
};

ENCOG.GUI.Agents2D.create = function (id, canvasWidth, canvasHeight) {
    'use strict';
    var result = new ENCOG.GUI.Agents2D();

    result.canvasDiv = document.getElementById(id);
    result.canvasWidth = canvasWidth;
    result.canvasHeight = canvasHeight;
    result.canvasDiv.innerHTML = '<canvas width="'
        + canvasWidth + '" height="' + canvasHeight + '">Browser not supported.</canvas>';
    result.canvas = result.canvasDiv.getElementsByTagName('canvas')[0];
    result.drawingContext = result.canvas.getContext('2d');

    // Attach the mousedown, mousemove and mouseup event listeners.
    result.canvas.addEventListener('mousedown', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mousemove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseup', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchstart', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchend', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchmove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseout', function (e) {
        result.ev_canvas(e)
    }, true);


    return result;
};

ENCOG.GUI.Agents2D.prototype =
{
    canvas:null,
    drawingContext:null,
    canvasDiv:null,
    NAME:"Agents2D",
    canvasWidth:null,
    canvasHeight:null,
    agents:null,
    agentSize:10,
    agentSpeed:5,
    pointerDown:null,
    pointerUp:null,
    pointerMove:null,
    captureTouch:true,


    // Handle events to the canvas.  This allows drawing to occur.
    ev_canvas:function (ev) {

    },
    reset:function (count) {
        'use strict';
        this.agents = [];
        for (var i = 0; i < count; i++) {
            this.agents[i] = [
                Math.floor(Math.random() * this.canvas.width),
                Math.floor(Math.random() * this.canvas.height),
                Math.floor(Math.random() * 360)];
        }
        this.render();
    },
    advance:function () {
        'use strict';
        var aff, r, r2, dy, dx, x, y, x2, y2, x3, y3, meanX, meanY, dx, dy, targetAngle, neighbors, nearest;
        var separation, alignment, cohesion, turnAmount;

        // loop over all agents
        for (var i = 0; i < this.agents.length; i++) {
            // Each particle is moving in a fixed speed in a direction
            // specified by the 2nd array element of the particle.
            // Adjust the X & Y (stored in the first/second array element)
            // to reflect this movement.
            r = this.agents[i][2] * (Math.PI / 180.0);
            dy = Math.cos(r);
            dx = Math.sin(r);
            this.agents[i][0] += (dx * this.agentSpeed);
            this.agents[i][1] += (dy * this.agentSpeed);

            // Bound.  Handle particles that fly off the edge of the universe.
            // These particles will loop to the other side of the universe.
            if (this.agents[i][0] < 0) {
                this.agents[i][0] = this.canvas.width;
            }
            else if (this.agents[i][0] > this.canvas.width) {
                this.agents[i][0] = 0;
            }

            if (this.agents[i][1] < 0) {
                this.agents[i][1] = this.canvas.height;
            }
            else if (this.agents[i][1] > this.canvas.height) {
                this.agents[i][1] = 0;
            }
        }
    },
    render:function () {
        'use strict';
        var aff, r, r2, dy, dx, x, y, x2, y2, x3, y3, meanX, meanY, dx, dy, targetAngle, neighbors, nearest, i;
        var separation, alignment, cohesion, turnAmount;

        // clear the canvas.
        this.canvas.width = this.canvas.width;

        // loop over all particles.
        for (i = 0; i < this.agents.length; i++) {
            // Draw the particle.  Each particle is s small traingle that
            // points in the direction that it is moving.
            x = this.agents[i][0];
            y = this.agents[i][1];

            r = (this.agents[i][2] + 180 - 15) * (Math.PI / 180.0);
            x2 = x + (Math.sin(r) * this.agentSize);
            y2 = y + (Math.cos(r) * this.agentSize);

            r2 = (this.agents[i][2] + 180 + 15) * (Math.PI / 180.0);
            x3 = x + (Math.sin(r2) * this.agentSize);
            y3 = y + (Math.cos(r2) * this.agentSize);

            this.drawingContext.strokeStyle = "#000000";
            this.drawingContext.beginPath();
            this.drawingContext.moveTo(x2, y2);
            this.drawingContext.lineTo(x, y);
            this.drawingContext.lineTo(x3, y3);
            this.drawingContext.closePath();
            this.drawingContext.stroke();
        }
    },
    // Plot gray lines to show an affinity group.  This is a particle and
    // all other particles that are neighbors.  If two flocks have no lines
    // between them, they have become independant.
    plotGroup:function (idx, others) {
        'use strict';
        var x1 = this.agents[idx][0];
        var y1 = this.agents[idx][1];

        for (var i = 0; i < others.length; i++) {
            var x2 = others[i][0];
            var y2 = others[i][1];

            this.drawingContext.strokeStyle = "#f0f0f0";
            this.drawingContext.beginPath();
            this.drawingContext.moveTo(x1, y1);
            this.drawingContext.lineTo(x2, y2);
            this.drawingContext.closePath();
            this.drawingContext.stroke();
        }
    },
    ev_canvas:function (ev) {

        if (ev.layerX || ev.layerX == 0) {
            ev._x = ev.layerX;
            ev._y = ev.layerY;
        }
        // Opera
        else if (ev.offsetX || ev.offsetX == 0) {
            ev._x = ev.offsetX;
            ev._y = ev.offsetY;
        }

        if (ev.type == 'mousedown' || ev.type == 'touchstart') {
            if (this.pointerDown != null) {
                this.pointerDown(ev._x, ev._y);
            }
        }
        else if (ev.type == 'mouseup' || ev.type == 'touchend') {
            if (this.pointerUp != null) {
                this.pointerUp(ev._x, ev._y);
            }
        }
        else if (ev.type == 'mousemove' || ev.type == 'touchmove') {
            if (this.pointerMove != null) {
                this.pointerMove(ev._x, ev._y);
            }
            if (this.captureTouch && ev.type == 'touchmove') {
                ev.preventDefault();
            }
        }
    }

};


////////////////////////////////////

ENCOG.GUI.TSP = function () {
    'use strict'
};

ENCOG.GUI.TSP.create = function (id, canvasWidth, canvasHeight) {
    'use strict';
    var result = new ENCOG.GUI.TSP();

    result.canvasDiv = document.getElementById(id);
    result.canvasWidth = canvasWidth;
    result.canvasHeight = canvasHeight;
    result.canvasDiv.innerHTML = '<canvas width="'
        + result.canvasWidth + '" height="' + result.canvasHeight + '">Browser not supported.</canvas>';
    result.canvas = result.canvasDiv.getElementsByTagName('canvas')[0];
    result.drawingContext = result.canvas.getContext('2d');

    // Attach the mousedown, mousemove and mouseup event listeners.
    result.canvas.addEventListener('mousedown', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mousemove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseup', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchstart', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchend', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('touchmove', function (e) {
        result.ev_canvas(e)
    }, true);
    result.canvas.addEventListener('mouseout', function (e) {
        result.ev_canvas(e)
    }, true);


    return result;
};

ENCOG.GUI.TSP.prototype =
{
    canvas:null,
    drawingContext:null,
    canvasDiv:null,
    NAME:"TSP",
    canvasWidth:null,
    canvasHeight:null,
    pointerDown:null,
    pointerUp:null,
    pointerMove:null,
    captureTouch:true,
    cities:null,
    currentPath:null,
    tspMargin:10,

    // Handle events to the canvas.  This allows drawing to occur.
    ev_canvas:function (ev) {

    },
    reset:function (count) {
        'use strict';
        var marginWidth, marginHeight;

        this.cities = [];
        marginWidth = this.canvas.width - (this.tspMargin * 2);
        marginHeight = this.canvas.height - (this.tspMargin * 2);

        for (var i = 0; i < count; i++) {
            this.cities[i] = new Array(
                Math.floor(Math.random() * marginWidth) + this.tspMargin,
                Math.floor(Math.random() * marginHeight) + this.tspMargin);
        }

        this.currentPath = this.generatePath();
        this.render();

    },

    resetCircle: function(count) {
        // reset the cities
        this.cities = [];
        var ratio = (2 * Math.PI) / count;
        var marginWidth = this.canvas.width - (this.tspMargin * 2);
        var marginHeight = this.canvas.height - (this.tspMargin * 2);

        for (var i = 0; i < count; i++) {
            var x = Math.floor(Math.cos(ratio * i) * (marginWidth / 2) + (marginWidth / 2)) + this.tspMargin;
            var y = Math.floor(Math.sin(ratio * i) * (marginHeight / 2) + (marginHeight / 2)) + this.tspMargin;
            this.cities[i] = [x, y];
        }

        this.currentPath = this.generatePath();
        this.render();
    },

    pathDistance:function (path, i1, i2) {
        return this.distance(this.cities[path[i1]], this.cities[path[i2]]);
    },
    distance:function (a1, a2) {
        var result = 0;
        for (var i = 0; i < a1.length; i++) {
            var diff = a1[i] - a2[i];
            result += diff * diff;
        }
        return Math.sqrt(result);
    },
    calculatePathLength:function (path) {
        var result = 0;

        for (var i = 0; i < path.length - 1; i++) {
            result += this.distance(this.cities[path[i]], this.cities[path[i + 1]]);
        }

        return result;
    },
    generatePath:function () {
        var taken = new Array(this.cities.length);
        var path = new Array(this.cities.length);

        for (var i = 0; i < this.cities.length; i++) {
            taken[i] = false;
        }

        for (var i = 0; i < this.cities.length - 1; i++) {
            var icandidate;
            do
            {
                icandidate = Math.floor(Math.random() * path.length);
            } while (taken[icandidate]);

            path[i] = icandidate;
            taken[icandidate] = true;

            if (i == path.length - 2) {
                icandidate = 0;
                while (taken[icandidate]) {
                    icandidate++;
                }
                path[i + 1] = icandidate;
            }
        }

        return path;
    },
    render:function () {
        'use strict';

        this.canvas.width = this.canvas.width;

        for (var i = 0; i < this.cities.length; i++) {
            this.drawingContext.fillStyle = "#0000FF";
            this.drawingContext.beginPath();
            this.drawingContext.arc(this.cities[i][0], this.cities[i][1], 5, 0, Math.PI * 2, true);
            this.drawingContext.closePath();
            this.drawingContext.fill();
        }

        for (var i = 0; i < this.cities.length - 1; i++) {
            this.drawingContext.strokeStyle = "#000000";
            this.drawingContext.beginPath();
            this.drawingContext.moveTo(this.cities[this.currentPath[i]][0], this.cities[this.currentPath[i]][1]);
            this.drawingContext.lineTo(this.cities[this.currentPath[i + 1]][0], this.cities[this.currentPath[i + 1]][1])
            this.drawingContext.closePath();
            this.drawingContext.stroke();
        }
    },
    ev_canvas:function (ev) {

        if (ev.layerX || ev.layerX == 0) {
            ev._x = ev.layerX;
            ev._y = ev.layerY;
        }
        // Opera
        else if (ev.offsetX || ev.offsetX == 0) {
            ev._x = ev.offsetX;
            ev._y = ev.offsetY;
        }

        if (ev.type == 'mousedown' || ev.type == 'touchstart') {
            if (this.pointerDown != null) {
                this.pointerDown(ev._x, ev._y);
            }
        }
        else if (ev.type == 'mouseup' || ev.type == 'touchend') {
            if (this.pointerUp != null) {
                this.pointerUp(ev._x, ev._y);
            }
        }
        else if (ev.type == 'mousemove' || ev.type == 'touchmove') {
            if (this.pointerMove != null) {
                this.pointerMove(ev._x, ev._y);
            }
            if (this.captureTouch && ev.type == 'touchmove') {
                ev.preventDefault();
            }
        }
    }

};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0

Share

About the Author

JeffHeaton
Architect
United States United States
Jeff Heaton is a data scientist, PhD student and indy publisher. Jeff works primarily in the programming languages Python, R, C#, Java and C/C++. He is an active technology blogger, open source contributor, and author of more than ten books. His areas of expertise include Data Science, Predictive Modeling, Data Mining, Big Data, Business Intelligence and Artificial Intelligence. He is the lead developer for the Encog Machine Learning Framework open source project. Jeff holds a Masters Degree in Information Management from Washington University, is a Senior Member of the IEEE, a Sun Certified Java Programmer and a Fellow of the Life Management Institute.
Follow on   Twitter   Google+   LinkedIn

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150414.1 | Last Updated 16 Oct 2012
Article Copyright 2012 by JeffHeaton
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid