terça-feira, 24 de março de 2020

Tangentes e Gráficos em javaScript



UNB-Matemática
Autor: Luiz Augusto Prado 1807787/DF
Blog: tivideotutoriais.blogspot.com

Nesta página apresento um pouco sobre tangentes e gráficos (ver javascript no fonte da página).
É permitido o uso e adaptação destes códigos fontes (javaScripts), desde que seja devidamente citada a fonte (por favor, deixe de mesquinhagem, cite suas fontes).
Se deseja ocultar a fonte ou entender melhor o código fonte, contrate nossa consultoria.

============================================
Tangentes e Gráficos:
============================================

O valor de uma tangente representa o quanto uma reta está inclinada.
Se a reta tem tangente igual a zero significa que ela é paralela ao eixo x.
Se a reta tem tangente maior que zero, significa que ela é crescente.
Se a reta tem tangente menor que zero, significa que ela é decrescente.

Se qualquer ponto P pode ser representado por um par de coordenadas (x ; y), então podemos representar os pontos iniciais e finais de uma reta tangente assim:
Po = ( xo ; yo) será o ponto de origem da tangente
Pf = ( xf ; yf) será o ponto final da tangente
Se Δx = xf - xo, mostrado em verde e
Se Δy = yf - yo, mostrado em azul
A inclinação da reta tangente, em vermelho, é dada por Δy/Δx
Observe que temos o equivalente seno/cosseno:




Se Po = (1;1) e Pf = (8;5)
Então
Δx = xf - xo = 8-1 → Δx = 7
Δy = yf - yo = 5-1 → Δy = 4
Logo Δy/Δx = 4/7

O sinal da tangente depende do quadrante em que o ângulo que a produz está:
Se entre 0° e 90°= sinal += reta crescente
Se entre 90° e 180°= sinal -= reta decrescente
Se entre 180° e 270°= sinal += reta crescente
Se entre 270° e 360°= sinal -= reta decrescente

Tangentes que terão módulo = 1:
45°=+1= reta crescente
135°= - 1= reta decrescente
225° (mesmo que -135°)=+1= reta crescente
315° (mesmo que -45°)= - 1= reta decrescente

Angulos que estão entre 45° e 315° (-45°) e entre 135° e 225° possuirão módulo<1;

Angulos que estão entre 45° e 135° e entre 225° e 315°(-45°) possuirão módulo>1

Para analisar os sinais e os módulos vejam que existem partições intercaladas pelos pontos onde as tangentes apresentam módulos=1 e onde os sinais trocam de sinal. Estas tangentes dividem ao meio cada partição falada:

Se entre 0° e 45°= modulo<1 = sinal += reta crescenteExemplo: tan( 0+45/2) = 0.41421356237309503
Se entre 45° e 90°= modulo>1 = sinal += reta crescenteExemplo: tan(90-45/2) = 2.414213562373095
Se entre 90° e 135°= modulo>1 = sinal -= reta decrescenteExemplo: tan(90+45/2) = -2.4142135623730954
Se entre 135° e 180°= modulo<1 = sinal -= reta decrescenteExemplo: tan(180-45/2) = -0.41421356237309515
Se entre 180° e 225°= modulo<1 = sinal += reta crescenteExemplo: tan(180+45/2) = 0.41421356237309437
Se entre 225° e 270°= modulo>1 = sinal += reta crescenteExemplo: tan(270-45/2) = 2.414213562373097
Se entre 270° e 315°= modulo>1 = sinal -= reta decrescenteExemplo: tan(270+45/2) = -2.4142135623730936
Se entre 315° e 360°= modulo<1 = sinal -= reta decrescenteExemplo: tan( 0 -45/2) = -0.41421356237309503

Compare os valores acima com √2 = 1.41421356237309
A tangente do ângulo 45°/2=22.5°, ou seja, tan(22.5°) = 1/(√2+1) = seno(22.5)/cosseno(22.5).
O cosseno(22.5) = 0.9238795325112867 é o comprimento da reta verde abaixo.
O seno ( 22.5) = 0.3826834323650898 é o comprimento da reta azul abaixo.
Independente do comprimento das retas, a reta verde é √2+1 vezes maior que a azul.




cosseno(45/3) = 0.9659258262890683 é o comprimento da reta verde abaixo
seno ( 45/3) = 0.25881904510252074 é o comprimento da reta azul abaixo
Independente do comprimento das retas, a reta verde é √3+2 vezes maior que a azul.




Algumas tangentes fáceis* de se obter são mostradas abaixo.
* Fácil no sentido de apresentar:
- Ângulos na forma a/b onde a e b são inteiros
- Terem raízes inteiras na formula de produção das tangentes
Note as formulas genéricas para estes casos:
[raiz(raiz(inteiro)+a)) + raiz(raiz(inteiro)-b))]/2 e
[raiz(raiz(inteiro)+a)) - raiz(raiz(inteiro)-b))]/2 para elas.
Tente encontrar outras formulas:

Angulo1 = 30
Angulo2 = 60
tang1 = raiz(3)/3
tang2 = raiz(3)

Angulo1 = 45
Angulo2 = 45
tan1 = [raiz(raiz(1)+3))+raiz(raiz(1)-1))]/2
tan2 = [raiz(raiz(1)+3))-raiz(raiz(1)-1))]/2

Angulo1 = 22.5
Angulo2 = 67.5
tan1 = [raiz(raiz(1)+7))+raiz(raiz(1)+3))]/2
tan2 = [raiz(raiz(1)+7))-raiz(raiz(1)+3))]/2

Angulo1 = 15
Angulo2 = 75
tan1 = [raiz(raiz(1)+15))+raiz(raiz(1)+11))]/2
tan2 = [raiz(raiz(1)+15))-raiz(raiz(1)+11))]/2

Angulo1 = 11.25
Angulo2 = 78.75
tan1 = [raiz(raiz(128)+16))+raiz(raiz(128)+12))]/2
tan2 = [raiz(raiz(128)+16))-raiz(raiz(128)+12))]/2

Angulo1 = 9
Angulo2 =81
tan1 = [raiz(raiz(320)+24))+raiz(raiz(320)+20))]/2
tan2 = [raiz(raiz(320)+24))-raiz(raiz(320)+20))]/2

Angulo1 = 7.5
Angulo2 =82.5
tan1 = [raiz(raiz(768)+32))+raiz(raiz(768)+28))]/2
tan2 = [raiz(raiz(768)+32))-raiz(raiz(768)+28))]/2


Focaremos em um modo para poduzir tangentes utilizando uma reta horizontal de tamanho 1 e um quadrado A de lado 'a' junto a esta reta. O exemplo abaixo permitirá que obtenhamos tangentes de ângulos entre 0° e 45° e consequentemente as outras 3 retas simétricas à primeira. Portanto, a partir deste modo, podemos construir qualquer tangente e obter um ângulo de origem para a tangente:
- seja invertendo o sinal da tangente para mudar o quadrante
- seja dividindo 1 pela tangente pra mudar o módulo
- seja dividindo 1 pela tangente e invertendo o sinal e para mudar o quadrante e o módulo




A reta, em verde, de comprimento 1 tem o Pox=0, ou seja, posicionado na origem.
O quadrado A de lado 'a', em azul, deve estar junto a reta, de forma que a lateral coincida com a reta.
O pondo inicial da reta tangente, em vermelho, está no Pox da reta verde, portanto Po=(0 ; 0).
O ponto final da reta tangente está no ponto superior esquerdo do quadrado, portanto Pf=(1-a ; a).
Deste modo temos que:
se Δx=xf-xo → Δx=1-a-0
se Δy=yf-yo → Δy=a-0
Então Δy/Δx=(a)/(1-a)

Portanto, ∀ a ∈ ℝ tal que 0 < a < 1/2 nos permitirá fazer qualquer tangente.



Equação reduzida da reta

Para qualquer tangente, existirá um valor n que correlaciona Δx e Δy da seguinte forma:
Δy=n*Δx → n*Δx - Δy = 0.
Se Δx = Pxf - Pxo onde Pxo=0
Se Δy = Pyf - Pyo onde Pyo=0 então
n*x = y


Cosseno em verde, seno em azul e tangente em vermelho:



Teorema de pitágoras

O comprimento da reta, em vermelho, NÃO pode ser confundido COM a tangente. A tangente é inclinação da reta. Isso independe do seu comprimento.

O comprimento da reta em vermelho pode ser caculado pelo teorema de pitágoras:
hipotenusa ao quadrado é igual ao quadrado do primeiro cateto (cosseno) mais o quadrado do segundo cateto (seno):
hipotenusa2 = cateto12 + cateto12 ou
h = √( c12 + c22 ) ou
1 = √( cos(x)2 + sen(x)2 )
Observe que se trabalhamos com seno e cosseno, estamos falando de valores que estão entre -1 e 1. Por isso, a hipotenusa, neste caso, valerá sempre 1.

Convertendo radianos para ângulos e ângulos para radianos

angulo = (radiano*180)/π

radiano= (angulo*π)/180

Exemplo 1:
Se temos 6.283185307179586 radianos ou (2π) e queremos um ângulo, basta fazermos:
(6.283185307179586 * 180)/3.141592653589793 = (2π * 180)/π → 180*2 = 360°

Exemplo 2:
Se temos 75° e queremos em radianos, basta fazermos:
(75 * π)/180 = (5 * π)/12




Códigos Fontes para Gráficos e alguns exemplos de uso

É permitido o uso e adaptação destes códigos fontes (javaScripts), desde que seja devidamente citada a fonte (Por favor, cite suas fontes).
Se deseja ocultar a fonte ou entender melhor o código fonte, contrate nossa consultoria.



//===================================================================
// Autor: Luiz Augusto Prado UNB 1807787/DF
//===================================================================

Grafico = function()
{
    this.image;
    this.ctx;
    this.showGrid;
    this.escala =1;
    this.w;
    this.h;
    this.corFundo ="#DDEFEE";
    this.corGrid ="#FFFFFF";
    this.corPontos="#0033FF";
    this.fontText ="10px Arial";

    this.maxX=-1000000000000000;
    this.minX= 1000000000000000;
    this.maxY=-1000000000000000;
    this.minY= 1000000000000000;
    this.dadosX=[];
    this.dadosY=[];
    this.menorEspacoX=1000000000000000;
    this.menorEspacoY=1000000000000000;
    this.maioresXY;
    this.menoresXY;
    this.escalaX;
    this.escalaY;

    this.cleanAllData = function()
    {
        this.maxX=-1000000000000000;
        this.minX= 1000000000000000;
        this.maxY=-1000000000000000;
        this.minY= 1000000000000000;
        this.dadosX=[];
        this.dadosY=[];
        this.menorEspacoX=1000000000000000;
        this.menorEspacoY=1000000000000000;
        this.maioresXY=[];
        this.menoresXY=[];
    }

    /*
    id é o nome que o canvas deverá ter
    w e h são as dimensões
    */
    this.createImage = function(id, w, h)
    {
        this.id=id;
        this.w=w;
        this.h=h;
        this.image = document.createElement("canvas");
        this.image.id=id;
        this.image.width=this.w;
        this.image.height=this.h;
        this.image.style.border='1px solid #6699CC';
        this.ctx = this.image.getContext("2d");
        document.body.appendChild(this.image);
        return this.image;
    }

    this.setEscala = function (escala)
    {
        this.escala=escala
    }

    /*
    componentId é o Id do componente onde a imagem deve ser criada. Uma div por exemplo.
    id é o nome que o canvas deverá ter
    w e h são as dimensões
    */
    this.createImageInside = function(componentId, id, w, h)
    {
        this.id=id;
        this.w=w;
        this.h=h;
        this.image = document.createElement("canvas");
        this.image.id=id;
        this.image.width=w;
        this.image.height=h;
        this.image.style.border='1px solid #6699CC';
        this.ctx = this.image.getContext("2d");
        document.getElementById(componentId).appendChild(this.image);
        return this.image;
    }

    this.setArray = function (arrayVetores)
    {
        for(var i=0; i<arrayVetores.length; i++)
        {
            for(var j=0; j<arrayVetores[i].length; j++)
            {
                x = arrayVetores[i][j][0] ;
                y = arrayVetores[i][j][1] ;
                if(this.maxX<x) this.maxX=x;
                if(this.minX>x) this.minX=x;
                if(this.maxY<y) this.maxY=y;
                if(this.minY>y) this.minY=y;

                var k=0;
                while(typeof this.dadosX[k]!=='undefined' && this.dadosX[k]<x)
                {
                    k++;
                }
                this.dadosX.splice(k, 0, x);

                var k=0;
                while(typeof this.dadosY[k]!=='undefined' && this.dadosY[k]<y)
                {
                    k++;
                }
                this.dadosY.splice(k, 0, y);

            }
        }
        for(var i=0; i<this.dadosX.length-1; i++)
        {
            if(this.dadosX[i+1]!=this.dadosX[i] && this.dadosX[i+1]-this.dadosX[i]<this.menorEspacoX)
                this.menorEspacoX=this.dadosX[i+1]-this.dadosX[i];

            if(this.dadosY[i+1]!=this.dadosY[i] && this.dadosY[i+1]-this.dadosY[i]<this.menorEspacoY)
                this.menorEspacoY=this.dadosY[i+1]-this.dadosY[i];

        }

        // para criar a melhor grid
        if(this.menorEspacoX<this.menorEspacoY) this.menoresXY= this.menorEspacoX
        this.menoresXY = this.menorEspacoY
        // para centralizar todos os vetores no meio da imagem
        this.maioresXY = [this.maxX-this.minX,this.maxY-this.minY];


    }

    this.plotGrid = function()
    {
        this.ctx.fillStyle=this.corFundo;
        this.ctx.fillRect(0, 0, this.w, this.h);
        // criar a grid
        if(this.showGrid)
        {
            //pelo menos dois eixos x e y devem passar pela origem
            this.ctx.strokeStyle=this.corGrid;
            this.ctx.globalAlpha=1;

            for(var x=0; x<this.w; x+=40)
            {
                this.ctx.beginPath();
                this.ctx.moveTo(x, 0);
                this.ctx.lineTo(x, this.h);
                this.ctx.stroke();
            }        
            for(var y=0; y<this.h; y+=40)
            {
                this.ctx.beginPath();
                this.ctx.moveTo(0 , y);
                this.ctx.lineTo(this.w , y);
                this.ctx.stroke();
            }
            this.ctx.globalAlpha=1;
        }
    }

    /*
    arrayVetores é uma matriz que contém:
     as matrizes de retas, que por sua vez contém:
     as matrizes de pontos (x;y)

    showPoints é uma matriz que contém:
     na posicao 0: uma matriz de textos que devem ser plotados.
     no posicao 1: uma matriz de pares de coordenadas (x,y)
    A posicao 1 indica onde cada texto deve aparecer
    Se este for nulo sera plotado todos os pontos das retas
    de acordo com as cores de cada reta
    Se este for um array vazio, não plotará nenhum ponto

    cores é uma matriz de cores para cada conjunto de retas

    showGrid mostra ou não a grid
    */
    this.plot = function(arrayVetores, showPoints, cores, showGrid, ProportionalScale)
    {
        this.cleanAllData();
        this.showGrid=showGrid;
        this.setArray(arrayVetores);
        this.plotGrid();


        if(ProportionalScale)
        {
            if( this.maioresXY[1]/this.maioresXY[0]<this.maioresXY[0]/this.maioresXY[1])
            {
                this.escalaX = this.w/this.maioresXY[0];
                //this.escalaY = this.h/this.maioresXY[1];
                this.escalaY = this.escalaX;
            }
            else
            {
                this.escalaY = this.h/this.maioresXY[1];
                //this.escalaX = this.w/this.maioresXY[0];
                this.escalaX = this.escalaY ;
            }
        }
        else
        {
            this.escalaX = this.w/this.maioresXY[0];
            this.escalaY = this.h/this.maioresXY[1];
        }
        
        this.escalaX *=this.escala;
        this.escalaY *=this.escala;

        //plotar matriz de pontos
        for(var i=0; i<arrayVetores.length; i++)
        {
            this.ctx.strokeStyle=cores[i];
            this.ctx.fillStyle=cores[i];
            for(var j=0; j<arrayVetores[i].length-1; j++)
            {
                a = -(this.maioresXY[0]/2 +this.minX);
                b = -(this.maioresXY[1]/2 +this.minY);
                x1 = this.w/2;
                x2 = this.w/2;
                x1+= (arrayVetores[i][j ][0]+a)*this.escalaX ;
                x2+= (arrayVetores[i][j+1][0]+a)*this.escalaX ;
                y1 =this.h/2;
                y2 =this.h/2;
                y1+=-(arrayVetores[i][j][1] +b)*this.escalaY ;
                y2+=-(arrayVetores[i][j+1][1]+b)*this.escalaY ;


                if( showPoints==null )
                {
                    this.ctx.font = this.fontText;
                    this.ctx.fillText("("+arrayVetores[i][j][0].toFixed(4)+";"+ arrayVetores[i][j][1].toFixed(4)+")", x1+3, y1+15);
                }

                this.ctx.beginPath();
                this.ctx.moveTo(x1,y1);
                this.ctx.lineTo(x2,y2);
                this.ctx.stroke();
            }
        }

        if( showPoints!=null && 0<showPoints.length)
        {
            this.ctx.fillStyle=this.corPontos;
            for(var i=0; i<showPoints[0].length; i++)
            {
                a = -(this.maioresXY[0]/2 +this.minX)
                b = -(this.maioresXY[1]/2 +this.minY)
                x1 = this.w/2;
                x1+= (showPoints[1][i][0]+a)*this.escalaX ;
                y1 =this.h/2;
                y1+=-(showPoints[1][i][1]+b)*this.escalaY ;

                this.ctx.font = this.fontText;
                this.ctx.fillText( showPoints[0][i], x1+3, y1+15);
            }
        }
    }
}


//===================================================================
// Autor: Luiz Augusto Prado UNB 1807787/DF
//===================================================================


AllData = function(contentElement, w, h)
{
    this.w = w;
    this.h = h;

    this.contentElement = contentElement;
    this.contentElement.style.position='relative';
    this.contentElement.style.width=w+4;
    this.contentElement.style.heigth=h+4;
    this.grafico = new Grafico();

    this.canvas = this.grafico.createImage("gragico", w, h)
    this.canvas.style.position='absolute';
    this.canvas.style.top = 1;
    this.canvas.style.left= 1;
    this.contentElement.appendChild(this.canvas);

    this.btns=[];

    this.addButtomData = function(nome, cor, idHidden)
    {
        var btn = document.createElement('div');
        btn.id="B"+idHidden;

        btn.innerHTML=nome;
        btn.style.textAlign='center';
        btn.style.border='1px solid';
        btn.style.position='absolute';

        btn.style.width=Math.floor(this.w/3)-4;
        btn.style.top = this.h+(24*Math.floor(this.btns.length/3)) + 5;
        btn.style.left= [ Math.floor(1+ this.w/3 )*(this.btns.length%3) +2];

        btn.cor=cor;
        btn.disabled=false;
        btn.data=[]

        var tdados = document.getElementById(idHidden);
        if( tdados!=null )
        {
            btn.style.backgroundColor=btn.cor;
            var dados = (tdados.value.replace(/\n/g, '')).split(',');
            for(var i=0; i<dados.length; i++)
            {
                btn.data.push(Number(dados[i]))
            }
        }
        else
        {
            btn.style.backgroundColor='#DDDDDD';
        }


        this.contentElement.appendChild(btn);

        btn.onclick = function()
        {
            if(!this.disabled || this.data.length==0)
            {
                this.style.backgroundColor='#DDDDDD'
                this.disabled = true
        
            }
            else
            {
                this.disabled = false
                this.style.backgroundColor=this.cor
            }
        }
        this.btns.push(btn)
    }

    this.plot = function()
    {
        this.contentElement.style.height = this.h+(24*Math.floor(this.btns.length/3)) +4
        var shapes=[];
        var cores =[];
        for(var i=0; i<this.btns.length; i++)
        {
            if(!this.btns[i].disabled)
            {
                var shape=[];
                cores.push(this.btns[i].cor);
                for(var j=0; j<this.btns[i].data.length; j++)
            
                {
                    v = [ j*5 , this.btns[i].data[j] ];
                    shape.push(v);
                }
                shapes.push(shape);
            }
        }

        this.grafico.escala=0.9
        this.grafico.plot(shapes, [], cores, true, true)
    }
}


Exemplo de Gráfico dinâmico:




Vermelho
Verde
Azul
cos
sen
tan

















Nenhum comentário: