JSXGraph logo
JSXGraph
JSXGraph share

Share

Complex maps
QR code
<iframe 
    src="https://jsxgraph.uni-bayreuth.de/share/iframe/complex-maps" 
    style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" 
    name="JSXGraph example: Complex maps" 
    allowfullscreen
></iframe>
This code has to
    <select id="functionterms" style="max-width:300px">
        <option>z</option>
        <option>z + i</option>
        <option>2z</option>
        <option>-z</option>
        <option>iz</option>
        <option>(1+i)z</option>
        <option>conj(z)</option>
        <option>9/conj(z)</option>
        <option>Re(z)</option>
        <option>i Im(z)</option>
        <option>x+2iy</option>
        <option>z^2</option>
        <option>z^3</option>
        <option>1/z</option>
        <option>e^z</option>
    </select>

<div id="board-0-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-0" class="jxgbox" style="aspect-ratio: 1 / 1; width: 50%;" data-ar="1 / 1"></div>
</div>
<div id="board-1-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-1" class="jxgbox" style="aspect-ratio: 1 / 1; width: 50%;" data-ar="1 / 1"></div>
</div>


    <div style="width: 600px; display:grid; border: 1px black solid; grid-template-columns: 1fr 1fr; max-width: 100%; padding: 20px;">
        <p id="out_z" style="max-width:200px;"></p>
        <p id="out_fz" style="max-width:200px;"></p>
    </div>
<script type = "text/javascript"> 
    /*
    This example is licensed under a 
    Creative Commons Attribution ShareAlike 4.0 International License.
    https://creativecommons.org/licenses/by-sa/4.0/
    
    Please note you have to mention 
    The Center of Mobile Learning with Digital Technology
    in the credits.
    */
    
    const BOARDID0 = 'board-0';
    const BOARDID1 = 'board-1';
    const BOARDID = BOARDID0;

        const board = JXG.JSXGraph.initBoard(BOARDID0, {
            boundingbox: [-10, 10, 10, -10],
            keepaspectratio: false,
            axis: true,
            pan: { enabled: false },
            sketches: {
                enabled: true,
                0: { visible: true },
                1: { visible: true, strokeColor: JXG.palette.blue }
            }
        });
        var board2 = JXG.JSXGraph.initBoard(BOARDID1, {
            boundingbox: [-10, 10, 10, -10],
            keepaspectratio: false,
            axis: true,
            pan: { enabled: false },
            sketches: {
                enabled: true,
                0: { visible: true, strokeColor: JXG.palette.blue, strokeWidth: 3 }
            }
        });
        board.addChild(board2);
    
        var funcs = {
            'z': (z) => z,
            'z + i': (z) => {
                let i = new JXG.Complex(0, 1);
                return i.add(z);
            },
            '2z': (z) => {
                let w = new JXG.Complex(2, 0);
                return w.mult(z);
            },
            '-z': (z) => {
                let w = new JXG.Complex(-1, 0);
                return w.mult(z);
            },
            'iz': (z) => {
                let w = new JXG.Complex(0, 1);
                return w.mult(z);
            },
            '(1+i)z': (z) => {
                let w = new JXG.Complex(1, 1);
                return w.mult(z);
            },
            'conj(z)': (z) => {
                return JXG.C.conj(z);
            },
            '9/conj(z)': (z) => {
                let w = new JXG.Complex(9, 0);
                return JXG.C.div(w, JXG.C.conj(z));
            },
            'Re(z)': (z) => {
                return new JXG.Complex(z.real, 0);
            },
            'i Im(z)': (z) => {
                return new JXG.Complex(0, z.imaginary);
            },
            'x+2iy': (z) => {
                return new JXG.Complex(z.real, 2 * z.imaginary);
            },
            'z^2': (z) => {
                return z.mult(z);
            },
            'z^3': (z) => {
                let res = z.mult(z);
                return res.mult(z);
            },
            '1/z': (z) => {
                let one = new JXG.Complex(1, 1);
                return one.div(z);
            },
            'e^z': (z) => {
                let re = z.real,
                    im = z.imaginary,
                    s = Math.exp(re);
                return new JXG.Complex(s * Math.cos(im), s * Math.sin(im));
            }
        };
        var f = funcs['z'];
    
        setTimeout(function() {
            document.getElementById('functionterms').addEventListener('change', function(evt) {
                f = funcs[evt.target.value];
            });
        }, 500);
    
        var arr1 = board.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });
        var arr2 = board2.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });
    
        var map_curvepoint = function(pos) {
            var z, w;
    
            // We just have to care about the mapped data point.
            // The data point is handled by board.sketch automatically.
            z = new JXG.Complex(pos[0], pos[1]);
            w = f(z);
    
            // Regardless if mouse key pressed or not, write the coordinates and position the arrows.
    
            // Write coordinates of z and f(z)
            out_z.innerHTML = `z = ${z.toString(4)}`;
            out_fz.innerHTML = `f(z) = ${w.toString(4)}`;
    
            // Position the arrows
            arr1.point2.moveTo([z.real, z.imaginary]);
            arr2.point2.moveTo([w.real, w.imaginary]);
    
            // Only if mouse key pressed do sketching
            if (board.isSketching[0]) {
                board2.sketch.dataX.push(w.real);
                board2.sketch.dataY.push(w.imaginary);
            }
        };
    
        // On down in the left board, delete the curve in the right board.
        board.on('down', function(evt) {
            // Reset map curve
            board2.sketch.dataX = [];
            board2.sketch.dataY = [];
    
            // Grab the last actual mouse position and map it 
            map_curvepoint(this.getUsrCoordsOfMouse(evt));
        });
    
        board.on('move', function(evt, mode) {
            // Grab the last actual mouse position and map it 
            map_curvepoint(this.getUsrCoordsOfMouse(evt));
        });
 </script> 
/*
This example is licensed under a 
Creative Commons Attribution ShareAlike 4.0 International License.
https://creativecommons.org/licenses/by-sa/4.0/

Please note you have to mention 
The Center of Mobile Learning with Digital Technology
in the credits.
*/

const BOARDID0 = 'your_div_id_0'; // Insert your 1st board id here!
const BOARDID1 = 'your_div_id_1'; // Insert your 2nd board id here!

    const board = JXG.JSXGraph.initBoard(BOARDID0, {
        boundingbox: [-10, 10, 10, -10],
        keepaspectratio: false,
        axis: true,
        pan: { enabled: false },
        sketches: {
            enabled: true,
            0: { visible: true },
            1: { visible: true, strokeColor: JXG.palette.blue }
        }
    });
    var board2 = JXG.JSXGraph.initBoard(BOARDID1, {
        boundingbox: [-10, 10, 10, -10],
        keepaspectratio: false,
        axis: true,
        pan: { enabled: false },
        sketches: {
            enabled: true,
            0: { visible: true, strokeColor: JXG.palette.blue, strokeWidth: 3 }
        }
    });
    board.addChild(board2);

    var funcs = {
        'z': (z) => z,
        'z + i': (z) => {
            let i = new JXG.Complex(0, 1);
            return i.add(z);
        },
        '2z': (z) => {
            let w = new JXG.Complex(2, 0);
            return w.mult(z);
        },
        '-z': (z) => {
            let w = new JXG.Complex(-1, 0);
            return w.mult(z);
        },
        'iz': (z) => {
            let w = new JXG.Complex(0, 1);
            return w.mult(z);
        },
        '(1+i)z': (z) => {
            let w = new JXG.Complex(1, 1);
            return w.mult(z);
        },
        'conj(z)': (z) => {
            return JXG.C.conj(z);
        },
        '9/conj(z)': (z) => {
            let w = new JXG.Complex(9, 0);
            return JXG.C.div(w, JXG.C.conj(z));
        },
        'Re(z)': (z) => {
            return new JXG.Complex(z.real, 0);
        },
        'i Im(z)': (z) => {
            return new JXG.Complex(0, z.imaginary);
        },
        'x+2iy': (z) => {
            return new JXG.Complex(z.real, 2 * z.imaginary);
        },
        'z^2': (z) => {
            return z.mult(z);
        },
        'z^3': (z) => {
            let res = z.mult(z);
            return res.mult(z);
        },
        '1/z': (z) => {
            let one = new JXG.Complex(1, 1);
            return one.div(z);
        },
        'e^z': (z) => {
            let re = z.real,
                im = z.imaginary,
                s = Math.exp(re);
            return new JXG.Complex(s * Math.cos(im), s * Math.sin(im));
        }
    };
    var f = funcs['z'];

    setTimeout(function() {
        document.getElementById('functionterms').addEventListener('change', function(evt) {
            f = funcs[evt.target.value];
        });
    }, 500);

    var arr1 = board.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });
    var arr2 = board2.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });

    var map_curvepoint = function(pos) {
        var z, w;

        // We just have to care about the mapped data point.
        // The data point is handled by board.sketch automatically.
        z = new JXG.Complex(pos[0], pos[1]);
        w = f(z);

        // Regardless if mouse key pressed or not, write the coordinates and position the arrows.

        // Write coordinates of z and f(z)
        out_z.innerHTML = `z = ${z.toString(4)}`;
        out_fz.innerHTML = `f(z) = ${w.toString(4)}`;

        // Position the arrows
        arr1.point2.moveTo([z.real, z.imaginary]);
        arr2.point2.moveTo([w.real, w.imaginary]);

        // Only if mouse key pressed do sketching
        if (board.isSketching[0]) {
            board2.sketch.dataX.push(w.real);
            board2.sketch.dataY.push(w.imaginary);
        }
    };

    // On down in the left board, delete the curve in the right board.
    board.on('down', function(evt) {
        // Reset map curve
        board2.sketch.dataX = [];
        board2.sketch.dataY = [];

        // Grab the last actual mouse position and map it 
        map_curvepoint(this.getUsrCoordsOfMouse(evt));
    });

    board.on('move', function(evt, mode) {
        // Grab the last actual mouse position and map it 
        map_curvepoint(this.getUsrCoordsOfMouse(evt));
    });

Complex maps

Visualize complex function $w = f(z)$. Draw a curve with the mouse in the left panel (the domain) and its image under $f$ appears on the right. Heavily influenced by [an app by Terence Tao](https://teorth.github.io/tao-web/apps/elementary-complex-maps.html).

    <select id="functionterms" style="max-width:300px">
        <option>z</option>
        <option>z + i</option>
        <option>2z</option>
        <option>-z</option>
        <option>iz</option>
        <option>(1+i)z</option>
        <option>conj(z)</option>
        <option>9/conj(z)</option>
        <option>Re(z)</option>
        <option>i Im(z)</option>
        <option>x+2iy</option>
        <option>z^2</option>
        <option>z^3</option>
        <option>1/z</option>
        <option>e^z</option>
    </select>
// Define the ids of your boards in BOARDID0, BOARDID1,...

    const board = JXG.JSXGraph.initBoard(BOARDID0, {
        boundingbox: [-10, 10, 10, -10],
        keepaspectratio: false,
        axis: true,
        pan: { enabled: false },
        sketches: {
            enabled: true,
            0: { visible: true },
            1: { visible: true, strokeColor: JXG.palette.blue }
        }
    });
    var board2 = JXG.JSXGraph.initBoard(BOARDID1, {
        boundingbox: [-10, 10, 10, -10],
        keepaspectratio: false,
        axis: true,
        pan: { enabled: false },
        sketches: {
            enabled: true,
            0: { visible: true, strokeColor: JXG.palette.blue, strokeWidth: 3 }
        }
    });
    board.addChild(board2);

    var funcs = {
        'z': (z) => z,
        'z + i': (z) => {
            let i = new JXG.Complex(0, 1);
            return i.add(z);
        },
        '2z': (z) => {
            let w = new JXG.Complex(2, 0);
            return w.mult(z);
        },
        '-z': (z) => {
            let w = new JXG.Complex(-1, 0);
            return w.mult(z);
        },
        'iz': (z) => {
            let w = new JXG.Complex(0, 1);
            return w.mult(z);
        },
        '(1+i)z': (z) => {
            let w = new JXG.Complex(1, 1);
            return w.mult(z);
        },
        'conj(z)': (z) => {
            return JXG.C.conj(z);
        },
        '9/conj(z)': (z) => {
            let w = new JXG.Complex(9, 0);
            return JXG.C.div(w, JXG.C.conj(z));
        },
        'Re(z)': (z) => {
            return new JXG.Complex(z.real, 0);
        },
        'i Im(z)': (z) => {
            return new JXG.Complex(0, z.imaginary);
        },
        'x+2iy': (z) => {
            return new JXG.Complex(z.real, 2 * z.imaginary);
        },
        'z^2': (z) => {
            return z.mult(z);
        },
        'z^3': (z) => {
            let res = z.mult(z);
            return res.mult(z);
        },
        '1/z': (z) => {
            let one = new JXG.Complex(1, 1);
            return one.div(z);
        },
        'e^z': (z) => {
            let re = z.real,
                im = z.imaginary,
                s = Math.exp(re);
            return new JXG.Complex(s * Math.cos(im), s * Math.sin(im));
        }
    };
    var f = funcs['z'];

    setTimeout(function() {
        document.getElementById('functionterms').addEventListener('change', function(evt) {
            f = funcs[evt.target.value];
        });
    }, 500);

    var arr1 = board.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });
    var arr2 = board2.create('arrow', [[0, 0], [0, 0]], { highlight: false, fixed: true });

    var map_curvepoint = function(pos) {
        var z, w;

        // We just have to care about the mapped data point.
        // The data point is handled by board.sketch automatically.
        z = new JXG.Complex(pos[0], pos[1]);
        w = f(z);

        // Regardless if mouse key pressed or not, write the coordinates and position the arrows.

        // Write coordinates of z and f(z)
        out_z.innerHTML = `z = ${z.toString(4)}`;
        out_fz.innerHTML = `f(z) = ${w.toString(4)}`;

        // Position the arrows
        arr1.point2.moveTo([z.real, z.imaginary]);
        arr2.point2.moveTo([w.real, w.imaginary]);

        // Only if mouse key pressed do sketching
        if (board.isSketching[0]) {
            board2.sketch.dataX.push(w.real);
            board2.sketch.dataY.push(w.imaginary);
        }
    };

    // On down in the left board, delete the curve in the right board.
    board.on('down', function(evt) {
        // Reset map curve
        board2.sketch.dataX = [];
        board2.sketch.dataY = [];

        // Grab the last actual mouse position and map it 
        map_curvepoint(this.getUsrCoordsOfMouse(evt));
    });

    board.on('move', function(evt, mode) {
        // Grab the last actual mouse position and map it 
        map_curvepoint(this.getUsrCoordsOfMouse(evt));
    });
    <div style="width: 600px; display:grid; border: 1px black solid; grid-template-columns: 1fr 1fr; max-width: 100%; padding: 20px;">
        <p id="out_z" style="max-width:200px;"></p>
        <p id="out_fz" style="max-width:200px;"></p>
    </div>

license

This example is licensed under a Creative Commons Attribution ShareAlike 4.0 International License.
Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits.