JavaScript 3D - 2
O objetivo
é ocultar as arestas que ficam atrás do cubo 3D, isso é conseguido
facilmente ocultando o ponto que fica no fundo da tela, como foi
padronizado o eixo-z positivo para dentro da tela, o ponto oculto é
aquele que tem a maior coordenada-z. Para enxergar e compreender o que
está acontecento é preciso estudar o ponto no espaço, por isso foi
trantado alguns tópicos de geometria analítica.
Embora não tenha sido utilizado o Produto Vetorial, o Produto Escalar e
a Direção de Vista do Observador para encontrar o ponto oculto, seus
cálculos serão apresentados e também serão os mesmos desenhados no cubo
para que possamos observar a dinâmica do que acontesse.
A descrição de um desenho mostra o seu significado ou entendimento.
Além de enriquecer o conteúdo e dirime possíveis dúvidas de algum
leitor.
Como desenhar em três dimensões com medidas reais em tela de monitor ou
em um papel que possuem apenas duas dimensões?
A intenção não é apenas definir ponto, mas discutir essa definição,
algo muito importante para o prosseguimento da matéria.
A projeção de um objeto real 3D na tela do monitor (2D) é feita com
apenas a coordenada-x e a coordenada-y. A coordenada-z participa
normalmente dos cálculos da transformação de pontos, mas não foi
utilizada na projeção.
1. Ocultanto Arestas Traseiras
A técnica utilizada é simples, basta encontrar a maior coordenadas-z
que esse ponto
não
terá as três coordenadas na parte de trás do cubo
acarretando a não visualização das três faces que o interceptam.
.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="c" width="601" height="601"
style="border:1px solid #000000;">
O seu browser não suporta o elemento
canvas do HTML5.
Por favor, actualize o seu browser.
</canvas><br>
<button onclick="faz()">Ok</button><br><br>
<script>
var c_canvas =
document.getElementById("c");
var ctx =
c_canvas.getContext("2d");
function Point3D(x,y,z) {
this.x = x; //"this.x
=x significa que a variável global x (this.x não declarada até então) é
igual a variável interna x que é igual ao parâmtro x"
this.y = y; //"o parâmtro x poderia ter outro nome, this.x
refere se a variavel x com escopo igual onde a função esta inserida"
this.z = z; //"this.x, this.y e this.z variáveis globais
iguais aos parâmetros x, y e z da função Point3D"
this.rotateZ = function(angle) {// giro do
objeto no sentido anti-horario para os tres eixos
var rad, cosa, sina, x, y;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = this.x*cosa-this.y*sina; //"x, y e z são
novas variáveis internas da funcao e this.x, this.y e this.z são
as variáveis x, y e z globais"
y = this.x*sina+this.y*cosa;
return new Point3D(x, y,this.z);
}
this.rotateX = function(angle) {
var rad, cosa, sina, y, z;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = this.y*cosa-this.z*sina;
z = this.y*sina+this.z*cosa;
return new Point3D(this.x, y, z);
}
this.rotateY = function(angle) {
var rad, cosa, sina, z, x;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = this.z*cosa-this.x*sina;
x = this.z*sina+this.x*cosa;
return new Point3D(x,this.y, z);
}
this.translate = function(tx,ty,tz) {
return new Point3D(x + tx,y + ty,z + tz)
}
}
var xc = Math.ceil((601-1)/2);
var yc = Math.ceil((601-1)/2);
var zc = Math.ceil((601-1)/2); //"importantissimo:
zc no lado positivo do eixo z"
var w = 100;
var h = 100;
var dp = 100;
var xo = (xc - w/2);
var yo = (yc + h/2);
var zo = (zc - dp/2);
var x1 = (xc + w/2);
var y1 = (yc + h/2);
var z1 = (zc - dp/2);
var x2 = (xc + w/2);
var y2 = (yc + h/2);
var z2 = (zc + dp/2);
var x3 = (xc - w/2);
var y3 = (yc + h/2);
var z3 = (zc + dp/2);
var x4 = (xc - w/2);
var y4 = (yc - h/2);
var z4 = (zc - dp/2);
var x5 = (xc + w/2);
var y5 = (yc - h/2);
var z5 = (zc - dp/2);
var x6 = (xc + w/2);
var y6 = (yc - h/2);
var z6 = (zc + dp/2);
var x7 = (xc - w/2);
var y7 = (yc - h/2);
var z7 = (zc + dp/2);
var vertices = new Array();
vertices.push(new Point3D(xo, yo, zo));// vertice 0
vertices.push(new Point3D(x1, y1, z1));// vertice 1
vertices.push(new Point3D(x2, y2, z2));// vertice 2
vertices.push(new Point3D(x3, y3, z3));// vertice 3
vertices.push(new Point3D(x4, y4, z4));// vertice 4
vertices.push(new Point3D(x5, y5, z5));// vertice 5
vertices.push(new Point3D(x6, y6, z6));// vertice 6
vertices.push(new Point3D(x7, y7, z7));// vertice 7
var angle2 = -10;//"angulo de rotacao para
teste, escolha uma valor compativel"
function faz(){
ctx.clearRect(0,0,600,600);
var t = new Array();
angle2 = angle2+10;// "primeira execucao da funcao terá angle2=0"
if(angle2==360){angle2=0;}
// ao atingir 360 angle2 é igual a zero
for(
var i = 0; i < vertices.length; i++ ) {
var r =
vertices[i].translate(-xc,-yc,-zc).rotateX(angle2).rotateY(angle2).rotateZ(10).translate(xc,yc,zc);
t.push(r);
}
var faces = new Array();
faces.push([t[0],t[1],t[2],t[3]]);//face 0
faces.push([t[4],t[0],t[3],t[7]]);//face 1
faces.push([t[4],t[0],t[1],t[5]]);//face 2
faces.push([t[5],t[1],t[2],t[6]]);//face 3
faces.push([t[2],t[6],t[7],t[3]]);//face 4
faces.push([t[4],t[5],t[6],t[7]]);//face
5
document.getElementById("ida").innerHTML=angle2;
zoculto=0;//importantissimo para o inicio da
comparacao
for(i=0;i<7;i=i+1){
for(r=0;r<8;r=r+1){
if(t[i].z<t[r].z){ if(t[r].z
>zoculto){zoculto=t[r].z;a=r;}//"a é variável que guarda
o valor do índice do ponto oculto"
xoculto= t[a].x;
yoculto= t[a].y;
document.getElementById("idzoculto").innerHTML=zoculto;
document.getElementById("idxoculto").innerHTML=xoculto;
document.getElementById("idyoculto").innerHTML=yoculto;
document.getElementById("idr").innerHTML=a;
}//fecha o se
}//fecha
o for interno
switch (a) {
case 0:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[1].x,t[1].y); //face 0
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y); //face1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 1:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[2].x,t[2].y); //face 0
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[2].x,t[2].y); //face3
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 2:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.moveTo(t[0].x,t[0].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.stroke();
ctx.closePath();
break;
case 3:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 4:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[5].x,t[5].y); //face 5
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[3].x,t[3].y); //face 1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 5:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[6].x,t[6].y); //face 5
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[2].x,t[2].y);// face 3
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case
6:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[7].x,t[7].y); //face 5
ctx.lineTo(t[4].x,t[4].y);
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.stroke();
ctx.closePath();
break;
case
7:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
}//"fecha o caso ou
switch"
}//fecha o for externo
ctx.fillText("0", t[0].x, t[0].y); //"escrita
do pontos nos vertices"
ctx.fillText("1", t[1].x, t[1].y);
ctx.fillText("2", t[2].x, t[2].y);
ctx.fillText("3", t[3].x, t[3].y);
ctx.fillText("4", t[4].x, t[4].y);
ctx.fillText("5", t[5].x, t[5].y);
ctx.fillText("6", t[6].x, t[6].y);
ctx.fillText("7", t[7].x, t[7].y);
Po="xo="+t[0].x.toFixed(4)+" yo="+
t[0].y.toFixed(4)+" zo="+t[0].z.toFixed(4); //"posição dos pontos"
P1="x1="+t[1].x.toFixed(4)+" y1="+
t[1].y.toFixed(4)+" z1="+t[1].z.toFixed(4);
P2="x2="+t[2].x.toFixed(4)+" y2="+
t[2].y.toFixed(4)+" z2="+t[2].z.toFixed(4);
P3="x3="+t[3].x.toFixed(4)+" y3="+
t[3].y.toFixed(4)+" z3="+t[3].z.toFixed(4);
P4="x4="+t[4].x.toFixed(4)+" y4="+
t[4].y.toFixed(4)+" z4="+t[4].z.toFixed(4);
P5="x5="+t[5].x.toFixed(4)+" y5="+
t[5].y.toFixed(4)+" z4="+t[5].z.toFixed(4);
P6="x6="+t[6].x.toFixed(4)+" y6="+
t[6].y.toFixed(4)+" z6="+t[6].z.toFixed(4);
P7="x7="+t[7].x.toFixed(4)+" y7="+
t[7].y.toFixed(4)+" z7="+t[7].z.toFixed(4);
ctx.fillText("Po=>"+Po,10,400);
ctx.fillText("P1=>"+P1,10,415);
ctx.fillText("P2=>"+P2,10,430);
ctx.fillText("P3=>"+P3,10,445);
ctx.fillText("P4=>"+P4,10,460);
ctx.fillText("P5=>"+P5,10,475);
ctx.fillText("P6=>"+P6,10,490);
ctx.fillText("P7=>"+P7,10,505);
}// fecha a funcao faz
</script>
rotação =<span id="ida"></span>º<br>
<br>
Ponto oculto = <span id="idr"></span><br>
Coordenada-Z maior: Zmaior = <span
id="idzoculto"></span><br>
Coordenada-X = <span id="idxoculto"></span><br>
Coordenada-Y = <span id="idyoculto"></span><br>
</body>
</html>
Link para execução do código acima
Observações:
1) O cubo foi padronizado com o sistema de coordenadas com eixo-y para
baixo e eixo-z para dentro da tela.
2) O cubo foi criado com os pontos 0, 1, 2 e 3 formando a base e os
pontos 4, 5, 6 e 7 formando o topo. Foram acrescentados as arestas
entre os pontos 0 e 4, 1 e 5, 2 e 6, 3 e 7.
Há duas formas para as coordenadas dos
pontos Po, P1, P2, P3, P4, P5, P6 e P7:
Po = (Pox,Poy)
Pox = faces[0][0].x e Poy = faces[0][0].x
ou
Pox = t[0].x e Poy = t[0].y
O código abaixo desenha o cubo com
todas as arestas, inclusive as ocultas:
Repare que foi construido primeiro a base e o topo com oito pontos, as
laterais são ligações entre os pontos da base e do topo.
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0: base
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5: topo
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y); //face1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[0].x,t[0].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
1.1. Implementação do Código para
Ocultar o Ponto Traseiro e suas Arestas
A lógica consiste em
fazer dois looping (for) para comparar as sete coordenadas-z, o
segundo for é interno ao primeiro for, cada coordenada-z é comparada
com as demais. O primeiro for pega cada coordenada-z e o segundo for
percorrer todas as coordenadas para cada ciclo do primeiro for.
Cada rotação do cubo é pego a maior coordenada-z que
corresponderá ao ponto
oculto.
Com o ponto oculto achado
o cubo será criado sem esse ponto. Será utilizado o comando switch para desenhar o cubo sem o ponto oculto.
angle2=angle2 - 10;
if(angle2==360){angle2=0;}
// esta condição
zera a variável angle2
zoculto=0;
//importantissimo para o
funcionamento, após um ciclo de comparação (primeiro for) a variável zoculto inicia com valor
zero, ou seja, a cada execução da função faz() o zoculto inicia igual a 0 (zero).
//o primeiro for pega cada ponto e compara com todos os pontos
usando o segundo for
for(i=0;i<7;i=i+1){
for(r=0;r<8;r=r+1){
//se ponto anterior menor que o seguinte, e
se o ponto seguinte maior que zmaior, zmaior igual ao ponto seguinte.
if(t[i].z<t[r].z){ if(t[r].z
>zoculto){zoculto=t[r].z;a=r;} // "
a
é variável que guarda o valor do índice
do ponto oculto"
xoculto= t[a].x;
yoculto= t[a].y;
document.getElementById("idzoculto").innerHTML=zoculto;
document.getElementById("idxoculto").innerHTML=xoculto;
document.getElementById("idr").innerHTML=a;
}
//fecha o se
}
//fecha
o for interno
switch (a) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
}//fecha o for externo
O primeiro case desenhará o cubo sem as arestas que utilizam o vértice
0 (zero), ou seja, sem as arestas 0 - 1, 0 - 3 e 0 - 4, aplica-se o
mesmo raciocínio para dos demais case (1, 2, 3, 4, 5, 6 e 7). Cada case
é o índice do respectivo ponto, exemplo, case 1 corresponde ao ponto P1
= (t[1].x, t[1].y), utilize a figura do cubo acima para confirmação.
case 0:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[1].x,t[1].y); //face 0
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y); //face1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
A
cada rotação do angulo
angle2, os pontos motificam o seu posicionamento e será desenhado um novo cubo conforme o ponto
de maior coordenada-z.
Esse ponto corresponderá ao único
case que fará o desenho do cubo.
1.2. Implementação
do Código para Teste ou Visualização do Resultado
A instrução abaixo colocar
(posiciona no canvas) a letra 0
(zero) no vértice 0 (zero), o mesmo foi feito para os demais vértices.
Isto ajuda nos testes do código.
ctx.fillText("0", t[0].x, t[0].y); //"escrita do pontos nos vertices"
Idem para os demais vértices ...
A instrução abaixo escreve as
coordenadas do vértice 0 (zero), o mesmo foi feito para os demais
vértices. Isto ajuda nos testes do código:
Po="xo="+t[0].x.toFixed(4)+"
yo="+ t[0].y.toFixed(4)+" zo="+t[0].z.toFixed(4); //"posição dos pontos"
Idem para os demais vértices ...
A instrução abaixo coloca (posiciona no canvas) as
coordenadas do vértice 0 (zero), o mesmo foi feito para os demais
vértices. Isto ajuda nos testes do código:
ctx.fillText("Po=>"+Po,10,400);
Idem para os demais vértices ...
2. Outra Técnica
O próximo código é uma modificação do anterior, a técnica consistem em
desenhar primeiro o cubo com todas as arestas e depois redesenhar as
aresta ocultas com a mesma cor de fundo da tela (branco). O erro é que
as arestas brancas sempre se sobrepõe porque foram desenhadas por
último, talvez o uso de
inde-z resolva
o problema.
Cada
case correspondente ao
respectivo ponto oculto que possui a variável
a1 que
guarda os índices correspondentes aos pontos ocultos. Por exemplo. o
case 0: corresponde ao a = 0 (ponto 0) e ao a1 = [3,1,4] (pontos 3, 1 e
4 que formam as arestas ocultas). Prossegue da mesma forma para os
demais pontos.
zoculto=0;
//importantissimo para o
funcionamento do código
var a=0;
//importantíssimo para o
funcionamento do código
for(i=0;i<7;i=i+1){ //percorre os pontos de 0 a 6
for(r=0;r<8;r=r+1){ percorre os
pontos de 0 a 7
if(t[i].z<t[r].z){ if(t[r].z
>zoculto){zoculto=t[r].z;a=r;}
//compara
o primeiro ponto com todos os pontos, depois o segundo ponto com todos
os pontos, assim sucessivamente até a comparação do penultimo ponto com
todos os pontos.
xoculto= t[a].x;
yoculto= t[a].y;
document.getElementById("idzoculto").innerHTML=zoculto;
document.getElementById("idxoculto").innerHTML=xoculto;
document.getElementById("idyoculto").innerHTML=yoculto;
document.getElementById("idr").innerHTML=a;
}//fecha o se
}//fecha o for interno
switch (a) {
case 0:
a1=[3,1,4];
break;
case 1:
a1=[0,2,5];
break;
case 2:
a1=[1,3,6];
break;
case 3:
a1=[2,0,7];
break;
case 4:
a1=[7,5,0];
break;
case 5:
a1=[4,6,1];
break;
case 6:
a1=[5,7,2];
break;
case 7:
a1=[6,4,3];
break;
}
ctx.beginPath();
ctx.strokeStyle="#
FFFFFF";
// cor branca
ctx.lineWidth = 2;
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[0]].x,t[a1[0]].y);
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[1]].x,t[a1[1]].y);
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[2]].x,t[a1[2]].y);
ctx.stroke();
ctx.closePath();
}//fecha o for externo
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="c" width="601" height="601"
style="border:1px solid #000000;">
O seu browser não suporta o elemento
canvas do HTML5.
Por favor, actualize o seu browser.
</canvas><br>
<button onclick="faz()">Ok</button><br>
<script>
var c_canvas =
document.getElementById("c");
var ctx =
c_canvas.getContext("2d");
function Point3D(x,y,z) {
this.x = x;
//"this.x =x significa que a variável global x (não declarada até
então) é igual ao "
this.y = y;
//parametro x, o parâmtro x poderia ter outro nome
this.z = z;
this.rotateZ = function(angle) {// giro do objeto no sentido
anti-horario para os tres eixos
var rad, cosa, sina, x, y;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = this.x*cosa-this.y*sina; //"x é uma nova variável interna e this.x
é a variável x global"
y = this.x*sina+this.y*cosa;
return new Point3D(x, y,this.z); // entrada de novos parametros, em vez
de this.z poderia ser
}
//"apenas z (this.z = z), mas this.z se refere a variável
global
z"
this.rotateX = function(angle) {
var rad, cosa, sina, y, z;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = this.y*cosa-this.z*sina;
z = this.y*sina+this.z*cosa;
return new Point3D(this.x, y, z);
}
this.rotateY = function(angle) {
var rad, cosa, sina, z, x;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = this.z*cosa-this.x*sina;
x = this.z*sina+this.x*cosa;
return new Point3D(x,this.y, z);
}
this.translate = function(tx,ty,tz) {
return new Point3D(x + tx,y + ty,z + tz)
}
}
var xc = Math.ceil((601-1)/2);
var yc = Math.ceil((601-1)/2);
var zc = Math.ceil((601-1)/2); //"zc no lado positivo do eixo z"
var w = 100;
var h = 100;
var dp = 100;
var xo = (xc - w/2);
var yo = (yc + h/2);
var zo = (zc - dp/2);
var x1 = (xc + w/2);
var y1 = (yc + h/2);
var z1 = (zc - dp/2);
var x2 = (xc + w/2);
var y2 = (yc + h/2);
var z2 = (zc + dp/2);
var x3 = (xc - w/2);
var y3 = (yc + h/2);
var z3 = (zc + dp/2);
var x4 = (xc - w/2);
var y4 = (yc - h/2);
var z4 = (zc - dp/2);
var x5 = (xc + w/2);
var y5 = (yc - h/2);
var z5 = (zc - dp/2);
var x6 = (xc + w/2);
var y6 = (yc - h/2);
var z6 = (zc + dp/2);
var x7 = (xc - w/2);
var y7 = (yc - h/2);
var z7 = (zc + dp/2);
var vertices = new Array();
vertices.push(new Point3D(xo, yo, zo));// vertice 0
vertices.push(new Point3D(x1, y1, z1));// vertice 1
vertices.push(new Point3D(x2, y2, z2));// vertice 2
vertices.push(new Point3D(x3, y3, z3));// vertice 3
vertices.push(new Point3D(x4, y4, z4));// vertice 4
vertices.push(new Point3D(x5, y5, z5));// vertice 5
vertices.push(new Point3D(x6, y6, z6));// vertice 6
vertices.push(new Point3D(x7, y7, z7));// vertice 7
var angle2 = -10;
function faz(){
ctx.clearRect(0,0,600,600);
var t = new Array();
angle2 = angle2+10;
if(angle2==360){angle2=0;}
for(
var i = 0; i < vertices.length; i++ ) {
var r =
vertices[i].translate(-xc,-yc,-zc).rotateX(30).rotateY(angle2).rotateZ(angle2).translate(xc,yc,zc);
t.push(r);
}
var faces = new Array();
faces.push([t[0],t[1],t[2],t[3]]);//face 0
faces.push([t[4],t[0],t[3],t[7]]);//face 1
faces.push([t[4],t[0],t[1],t[5]]);//face 2
faces.push([t[5],t[1],t[2],t[6]]);//face 3
faces.push([t[2],t[6],t[7],t[3]]);//face 4
faces.push([t[4],t[5],t[6],t[7]]);//face
5
ctx.beginPath(); desenho do cubo com todas as arestas
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0: base
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5: topo
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y); //face1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[0].x,t[0].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
zoculto=0;//importantissimo
var a=0;//importantíssimo
for(i=0;i<7;i=i+1){
for(r=0;r<8;r=r+1){
if(t[i].z<t[r].z){ if(t[r].z
>zoculto){zoculto=t[r].z;a=r;}
xoculto= t[a].x;
yoculto= t[a].y;
document.getElementById("idzoculto").innerHTML=zoculto;
document.getElementById("idxoculto").innerHTML=xoculto;
document.getElementById("idyoculto").innerHTML=yoculto;
document.getElementById("idr").innerHTML=a;
}//fecha o se
}//fecha o for interno
switch (a) {
case 0:
a1=[3,1,4];
break;
case 1:
a1=[0,2,5];
break;
case 2:
a1=[1,3,6];
break;
case 3:
a1=[2,0,7];
break;
case 4:
a1=[7,5,0];
break;
case 5:
a1=[4,6,1];
break;
case 6:
a1=[5,7,2];
break;
case 7:
a1=[6,4,3];
break;
}
ctx.beginPath();
ctx.strokeStyle="#FFFFFF";
//cor branca
ctx.lineWidth = 2;
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[0]].x,t[a1[0]].y);
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[1]].x,t[a1[1]].y);
ctx.moveTo(t[a].x,t[a].y);
ctx.lineTo(t[a1[2]].x,t[a1[2]].y);
ctx.stroke();
ctx.closePath();
}//fecha o for externo
ctx.fillText("0", t[0].x, t[0].y); //"escrita do pontos nos vertices"
ctx.fillText("1", t[1].x, t[1].y);
ctx.fillText("2", t[2].x, t[2].y);
ctx.fillText("3", t[3].x, t[3].y);
ctx.fillText("4", t[4].x, t[4].y);
ctx.fillText("5", t[5].x, t[5].y);
ctx.fillText("6", t[6].x, t[6].y);
ctx.fillText("7", t[7].x, t[7].y);
Po="xo="+t[0].x.toFixed(4)+" yo="+
t[0].y.toFixed(4)+" zo="+t[0].z.toFixed(4); //"posição dos
pontos"
P1="x1="+t[1].x.toFixed(4)+" y1="+
t[1].y.toFixed(4)+" z1="+t[1].z.toFixed(4);
P2="x2="+t[2].x.toFixed(4)+" y2="+
t[2].y.toFixed(4)+" z2="+t[2].z.toFixed(4);
P3="x3="+t[3].x.toFixed(4)+" y3="+
t[3].y.toFixed(4)+" z3="+t[3].z.toFixed(4);
P4="x4="+t[4].x.toFixed(4)+" y4="+
t[4].y.toFixed(4)+" z4="+t[4].z.toFixed(4);
P5="x5="+t[5].x.toFixed(4)+" y5="+
t[5].y.toFixed(4)+" z4="+t[5].z.toFixed(4);
P6="x6="+t[6].x.toFixed(4)+" y6="+
t[6].y.toFixed(4)+" z6="+t[6].z.toFixed(4);
P7="x7="+t[7].x.toFixed(4)+" y7="+
t[7].y.toFixed(4)+" z7="+t[7].z.toFixed(4);
ctx.fillText("Po=>"+Po,10,400);
ctx.fillText("P1=>"+P1,10,415);
ctx.fillText("P2=>"+P2,10,430);
ctx.fillText("P3=>"+P3,10,445);
ctx.fillText("P4=>"+P4,10,460);
ctx.fillText("P5=>"+P5,10,475);
ctx.fillText("P6=>"+P6,10,490);
ctx.fillText("P7=>"+P7,10,505);
document.getElementById("ida").innerHTML=angle2;
}// fecha a funcao
faz
</script>
rotação =<span id="ida"></span>º<br>
<br>
Ponto oculto = <span id="idr"></span><br>
Coordenada-Z maior: Zmaior = <span
id="idzoculto"></span><br>
Coordenada-X = <span id="idxoculto"></span><br>
Coordenada-Y = <span id="idyoculto"></span><br>
</body>
</html>
Link para execução do código acima
Obs: O erro é que as arestas
brancas sempre se sobrepõe porque foram desenhadas por último, talvez o
uso de
inde-z resolva o
problema.
3. Produto Escalar, Produto vetorial e
Direção de Visualização
O objetivo deste item é calcular o produto vetorial e o produto
escalar e plotar (desenhar) o produto vetorial afim de dominar,
controlar e entender a dinâmica da rotação de pontos na tela do
monitor. Os vértices ocultos podem ser localizados através do
produto vetorial entre duas arestas e o ângulo entre o produto vetorial
(entre as duss arestas) e a direção de visualização do observador,
porém, não fará parte deste trabalho por motivo de tempo para
implementação que até nesta etapa já é considerável.
Testar o código significa confirmar a teoria através da
demonstração prática, vamos aprender a calcular o produto vetorial e o
produto escalar e desenhar o produto escalar com a finalidade de
dominar essa técnica tão útil Para localização do ponto no espaço.
3.1. Ponto
Grandeza escalar: é aquela
caracterizada por um número e sua unidade,
exemplos: 2 kg de massa, 10 metros de comprimento e 8 km² de área.
Grandeza vetorial:
necessidade de uma direção, uma intensidade ou
módulo e um sentido para sua determinação, exemplos: força, velocidade.
Vetor é a diferença entre dois pontos (extremidade menos
origem), é um segmento de reta
orientado, possui módulo, direção e sentido.
Ponto: em termos práticos é a localização de uma região
através de suas coordenadas,
não possui módulo, difereção ou sentido.

Seja A(a
x,a
y) e B(b
x,b
y)
dois pontos no primeiro quadrante do sistema cartesiano, então: B - A =
→AB e B =
→AB + A
Obs: A - B = -
→AB =
→BA

Pelo Teorema de pitágoras: |
→AB| = √
(bx-ax)²+(by-ay)²
O vetor
→AB no ponto A tem módulo igual a
zero. O vetor
→BA no ponto B tem módulo igual a
zero.
O vetor
→OA tem coordenadas iguais ao ponto
A, porém, subtração de pontos é diferente da subtração de vetores.
Repare
que o sentido surge com a diferença entre as coordenadas de dois pontos.
- Módulo de um vetor é a diferença entre as coordenadas do ponto de
extremindade com as coordenadas do ponto de origem do mesmo.
-
Um ponto não tem
módulo, mas tem coordenadas. Um vetor
tem módulo e diferença de coordenadas.
- Subtração de pontos é diferente de subtração de vetores.
Propriedades do Ponto
- Um ponto é determinado por suas coordenadas. As coordenadas são
obtidas pela projeção ortogonal do ponto nos eixos catesianos.
- Um ponto tem como referência a
origem do sistema de coordenadas.
- Um ponto considerado como vetor possui módulo nulo e tem origem e
extremidades coincidentes.
Propriedades do Vetor
- Possui módulo, direção e sentido.
- Fica determidado pela diferença entre o ponto de extremidade e o
ponto de origem.
- O sinal de menos (-) para os eixos significa sentido contrário ao
sentido positivo (+) ou contrário a seta de direção dos eixos.
- Quando multiplicamos um vetor por menos um (-1) o seu sentido é
invertido.
- Dois seguimentos são ditos equipolente se ambos são nulos ou ambos
tem
a mesma direção, o mesmo sentido e o mesmo comprimento.
- Um vetor é uma classe de equipolência de seguimentos orientados no
espaço (E³).
Um vetor não é alterado pela sua translação.
Propriedades da Adição de Vetores
- Associativa:
(
→ a +
→ b ) +
→ c =
→ a + (
→ b +
→ c )
- Soma:
→a = (ax
→ i ,ay
→ j ,az
→k )
→b = (bx
→ i ,by
→ j ,bz
→k )
→a +
→b = ((ax+bx)
→ i ,(ay+by)
→ j ,(az
+bz)→k )
- Diferença:
→a -
→b = ((ax-bx)
→ i ,(ay-by)
→ j ,(az
-bz)→k )
A propriedade asssossiativa possibilita deslocar qualquer ponto no
espaço apenas
somando-se vetores ao ponto: B = A +
→AB
Conforme figura abaixo:
→AB =
→ v1 +
→ v2 + → v3 + → v4 = → v3 + → v4 + → v1 + → v2
Paralelogramo
3.2. Projeção no Plano
A visão humana é capaz de ver os objetos em três dimenções, ou seja, o
comprimento na horizontal, o comprimento na vertical e comprimento de
profundidade.
A projeção de um objeto real (3D) no plano não possui o comprimento de
profundidade, isso torna desnecessário o uso da coordenada-z na
formação ou plotagem da imagem do objeto na tela. Ao gira um objeto 3D
no espaço, as coordenadas projetadas na tela vão mudando, porem, sempre
será projetada a coordenada-x e a coordenada-y do ponto, isso cria a
aparência de três dimensões. As coordenadas do eixo-z não aparecerão
porque são perpendiculares ao plano-xy.
3.2.1. Formação da Imagem
Para um objeto 3D um ponto tem três coordenadas P(x,y,z). Ao protar um
objeto 3D na tela do monitor utiliza-se apenas a coordenada-x e a
coordenada-y, P(x,y).
A rotação de um ponto em torno do eixo-z gerará um círculo no plano-xy,
a rotação de um ponto em torno do eixo-x ou eixo-y a projeção do ponto
percorerá uma reta em um sentido de 0º a 180º de rotação e retornará ao
ponto de origem (sentido contrário) de 180º a 360º. Isto acontece
porque a projeção é feita com apenas a coordenada-x ou a coordenada-y.
No plano-xy há duas coordenadas e a projeção é feita normalmente. No
plano-xz há apenas a coordenada-x uma vez que a coordenada-z não é
plotada. No plano-yz há apenas a coordenada-y uma vez que a
coordenada-z não é plotada.
A figura abaixo mostra um ponto que girou 360º no plano-xz de forma
que sua projeção formou uma reta, coordenada-y = 0. De 0º a 180º (
frente) a
projeção deslocou-se para à esquerda e de 180º a 360° (
traseira)
a projeção
deslocou-se para a direita. Isto acontece quanado é utilizado apenas a
coordenada-x e a coordenada-y para a projeção de um objeto 3D no plano.
Projeção do Cubo Tridimencional no
Plano-XY (tela)
Ignorar a coordenada-z e plotar o objeto 3D no plano-xy equivale a uma
imagem em que a direção da vista do observador é exatamente igual a do
eixo-z, ou seja, o olho do observador está no eixo-z.
O
segredo está em utilizar três coordenadas (x,y e z) reais para os
cálculos
e plotar (desenhar, projetar) apenas a coordenada-x e a coordenada-y.
Isso significa que
estamos projetanto o cubo tridimencional no plano-xy. A DESVANTAGEM
DESTA TÉCNICA É QUE AS PROJEÇÕES NO PLANO-XZ E PLANO-YZ SERÃO
PROJETADAS APENAS A COORDENADA-X E A COORDENADA-Y RESPECTIVAMENTE.
Teste Realizado:
A imgem abaixo mostra a rotação dos pontos em torno dos eixos. A
rotação de 10º dos pontos em torno do eixo-x no sentido anti-horário
que deslocou as coordenadas-y para baixo. A rotação de 10º dos pontos
em torno do eixo-y no sentido anti-horário deslocou as coordenadas-x
para à esquerda.
3.3. Perspectiva
Na perspectiva tudo que se desenha pertence ao plano formado pelo
eixo-x e pelo
eixo-y,
até mesmo o eixo-z pertence a esse
plano. Na área técnica a
dimensão é mais importante do que a visualização, pois a medida deve
ser exata, por isso a projeção no eixo-z deve ser real assim como no
eixo-x e eixo-y.
Na figura abaixo a primeira face do cubo é real (eixo-x e eixo-y), as
coordenadas no eixo-z possuem o tamanho real e foram obtidas da rotação
do ponto.
A aparência é de uma paralelepípedo e não de um cubo.
Repare na figura abaixo que tanto a perspectiva quanto um cubo real ao
ser rotacionado utilizam a regra da mão direita (no caso da figura
abaixo).
As coordenadas em três dimenções do objeto real e as coordenadas em
duas dimensões da
perspectiva possuem a mesma dinâmica ao rotacionar o objeto real. Ao
rotacionar o objeto a coordenada do eixo-z (não visível) passa a ser
coordenada do eixo-x e/ou coordenada do eixo-y, portanto projetável na
tela.
A vantagem desta perspectiva é que
cada ponto possui nitidamente as três coordenadas P(x,y,z).

0P9 = b
00' = b
P1P2 =
P2P3 =
P3P4 =
P4P1 =
P4P6 =
P3P5 =
P1P7 =
P2P8 =
P7P6 =
P6P5 =
P5P8 =
P8P7 = b
â: varia conforme a posição do ponto P1 e do comprimento b.
sen(â) = b/r
ê:
se de fato o eixo-z existisse o triângulo OP4P6 seria retângulo e não
isóceles. As coordenadas dos pontos 3D existem e são utilizadas para os
cálculos que forem necessário normalmete, porém, quando os pontos 3D
forem plotados na tela, apenas as coordenadas-x e as coordenadas-y são
utilizadas. As coordenadas-z serão formadas no plano 2D pelas ligação
dos pontos P(x,y) que correspondem com a respectiva coordenada-z do
próprio ponto.
sen(ê/2) = (b/2)/r
3.4. Perspectiva Isométrica
A figura abaixo é uma perspectiva em que o eixo-z e o eixo-x formam 60º
com o eixo-y, porém devemos interpretar como 90º. As dimensões do cubo
em perspectiva mudam conforme rotacionamos os três eixos.
Esta perspectiva é a projeção real da coodenada-x e da coordenada-y do
objeto no plano-xy da tela. Ao girar o objeto a coordenada-z vai se
projetanto no plano-xy, ou melhor, as três coordenadas vão mudando de
tamanho.
A perspectiva da figura abaixo formou um hexaedro que
foi circunscrito por uma circunferência de raio igual ao lado do
hexaedro. O
graus
de realismo depende da espessura e forma das linhas, sombras, degrades,
luminosidade, brilho, ofuscamento, tons, cores, fundo, etc.

Obs: Cada ponto da perspectiva acima tem apenas duas coordenadas, mesmo
representando um objeto no espaço 3D, ou seja, os pontos estão em um
plano.
Esta técnica consistem em desenhar ou plotar o cubo 3D na tela, porém
os pontos 3D serão inseridos nas coordenadas da perspectiva. Devemos
transformar os pontos do cubo 3D para a perspectiva.
Para o cubo 3D x = y = z = b.
P2'(x2',y2',z2')
cos30º = x2'/x2 => x2' = x2.cos30º
sen30º = y2'/x2' => y2' = x2'.sen30º
z2' = z2 = 0
P2' = (x2.cos30º,x2'.sos30º,0)
P3'(x3',y3',z3')
sen60º = x3'/x3 => x3' = x3.sen60º
y3' = y3 + y3.cos30º
z3' = z3 = 0
P3' = (x3.cos30º,y3 + y3.cos30º,0)
...
Com um cubo foi obtido aparentemente um hexaedro com giro de 45º para o
eixo-x, 35º para o eixo-y e 0º para o eixo-z.
Na figura abaixo temos o ciclo (ou círculo) trigonométrico com as
variações das
coordenadas
do
ponto (cosα,senα),
como o círculo tem raio igual a 1 (um), o cosseno e o seno tem valores
que
variam de -1 a 1.
De 0º a 360º cosseno e seno vão de 1 à -1
De 0º a 180º cosseno vai de 1 a -1. E seno vai de 0 à 1 e de 1 à 0.
Quando um ponto gira com seu centro na origem do sistema de
coordenadas, as coordenadas de um eixo aumentam e as coordenadas
do
outro do eixo diminuem e vice versa.
Reiniciar
3.5. Rotação de Ponto em Torno do Eixo
A figura abaixo mostra a rotação do ponto
P no sentido anti-horário em torno
dos três eixos. Os eixos de referências permanecem parados.
O
ponto P possui as projeções Px, Py e Pz nos respectivos eixos.

Ao
rotacionar um ponto em torno de um eixo ele o faz através de um raio de
circunferência igual a projeção do ponto no plano formado pelos outros
dois eixos.
Todos os
pontos de um objeto seguem esta mesma regra.
O eixo sobre o qual o ponto gira matém a mesma coordenada e as
coordenadas dos outros dois eixos mudam.
Uma rotação em torno de um eixo provoca a alteração das coordenadas nos
outros dois eixos conforme a circunferência pontilhada. A alteração das
coordenadas é no sentidos positivo ou negativo do respectivo eixo
conforme sua posição na circunferência de giro do ponto.
Ao girar um ponto:
Suas projeçãos nos eixos podem deslocar-se no sentido positivo ou
negativo conforme a sua posição na circunferência pontilhada.
Sistema de Referência
É o da
tela do monitor, eixo-x na horizontal e eixo-y na vertical, o eixo-z é
fictício. Ao rotacionar um objeto no espaço 3D a coordenada-z se
transformará em coordenada-x e cordenada-y,ou seja, será projetada no
plano-xy.
O sistema de
coordenadas de referência permanecer sempre parado, pois é uma
referência, o que muda é o sistema de coordenadas do objeto que muda
junto com ele.
Com a Regra da
Mão Direita: par o giro do objeto no espaço 3D.
Rotação
|
Anti-horário
|
Horário
|
 |
do
eixo-z
|
x'
= x.cosθ
- y.senθ
y' = x.senθ
+ y.cosθ |
x'
= x.cosθ + y.senθ
y' = -x.senθ
+ y.cosθ |
do
eixo-y
|
x'
= z.cosθ
- x.senθ
y' = z.senθ
+ x.cosθ |
x'
= z.cosθ + x.senθ
y' = -z.senθ
+ x.cosθ |
do
eixo-x
|
x'
= y.cosθ
- z.senθ
y' = y.senθ
+ z.cosθ |
x'
= y.cosθ + z.senθ
y' = -y.senθ
+ z.cosθ |
Quando eu olho de frente para um objeto no espaço 3D e o rotaciono no
sentido anti-horário, para ter este mesmo efeito na tela do monitor eu
preciso padronizar o sistema de coordenadas de referência do objeto e
da imagem, ou sejam tem que ser o mesmo. Assim, se o objeto gira no
sentido anti-horário a imagem tambem gira no sentido anti-horário.
4. Padronização dos Pontos
É preciso criar uma regra lógica para facilitar o entendimento e
organizar a disposição dos pontos de forma correta.
Essa disposição dos eixos foi escolhida por representar a tela de um
monitor em três dimensões, o eixo-z avança para dentro. Será usado o
mesmo sentido do eixo-y da tela para não prejudicar a edição de
textos para indicar os vértices. O cubo possui lado igual a dois (2).
O
importante é escolher uma disposição dos pontos no cubo igual a
configuração da tela do monitor e utilizar a mesma disposição para os
cálculos.
Os vértices serão
representados por letras e números.
Repare que o cubo padrão (2x2) é a base para a criação do cubo
de lados w, h e dp, centralizado em C(xc,yc,zc).
Cubo 2x2 (y
para baixo) |
Vértices (mão
direita) |
P(x,y,z)
|
 |
Po(-1,1,-1)
P1(1,1,-1)
P2(1,1,1)
P3(-1,1,1)
P4(-1,-1,-1)
P5(1,-1,-1)
P6(1,-1,1)
P7(-1,-1,1)
|
xo = (xc - w/2);
yo = (yc + h/2);
zo = (zc - dp/2);
x1 = (xc + w/2);
y1 = (yc + h/2);
z1 = (zc - dp/2);
x2 = (xc + w/2);
y2 = (yc + h/2);
z2 = (zc + dp/2);
x3 = (xc - w/2);
y3 = (yc + h/2);
z3 = (zc + dp/2);
x4 = (xc - w/2);
y4 = (yc - h/2);
z4 = (zc - dp/2);
x5 = (xc + w/2);
y5 = (yc - h/2);
z5 = (zc - dp/2);
x6 = (xc + w/2);
y6 = (yc - h/2);
z6 = (zc + dp/2);
x7 = (xc - w/2);
y7 = (yc - h/2);
z7 = (zc + dp/2) |
5. Versor
É um vetor unário que representa a mesma orientação do seu
respectivo eixo, ou seja, mesma direção e sentido.
Pojeção dos Versores
Os versores representam o sentido positivo dos eixos do espaço
tridimensional.

Módulo igual a 1:
i = (1,0,0)
j = (0,1,0)
k = (0,0,1)
|
→ i | = 1
|
→ j | = 1
|
→ k | = 1
Pelo Teorema de Pitágora: hipotenusa
2 = cateto1
2
+ cateto2
2
podemos calcular a diagonal de um retângulo qualquer.
As projeções de um vetor
v no espaço formam
um retângulo cuja diagonal corresponde a seu módulo.
|
→v | = √
x² + y² + z²
Para um cubo de lados iguais a
c, sua diagonal
d é:
d = c.√
3
Discussão:
- Um ponto no espaço pode ocupar qualquer posição e suas projeções não
formam necessariamente um cubo no sistema de coordenadas cartesiano.
- Os versores possibilitam trabalhar com apenas os módulos das
projeções dos vetores no espaço, despreocupando assim com sua direção e
sentido.
- As projeções de um vetor no espaço formam um paralelogramo.
6. Produto Escalar
Adaptando a figura anterior para o produto escalar temos:
(
→ i ,
→ j ,
→ k)
→ v = (x
v, y
v,
z
v)
→ u = (x
u, y
u,
z
u)
Obs: θ varia de 0º a 180º
apenas.
→PQ =
→ v -
→ u
→PQ = (x
v, y
v,
z
v) - (x
u, y
u, z
u) = (x
v-xu
,
y
v-y
u, z
v-z
u)
|
→PQ| =√
(xv-xu)²
+ (yv-yu)² + (zv-zu)²
|
→PQ|² = (x
v-x
u)²
+ (y
v-y
u)² + (z
v-z
u)²
|
→PQ|² = (x²
v-2.x
v.x
u+x²
u)
+ (y²
v-2.y
v.y
u+y
²u) + (z²
v-2.z
v.z
u+z²
u)
|
→PQ|² = (x²
v+y²
v+z²
v)
+ (x²
u+y
²u+z²
u) -2[(x
v.x
u)
+ (y
v.y
u) + (z
v.z
u)]
(x²
v+y²
v+z²
v) = v² e (x²
u+y
²u+z²
u)
= u²
|
→PQ|² = v² + u² -2[(x
v.x
u)
+ (y
v.y
u) + (z
v.z
u)]
(I) No Espaço
Em qualquer triângulo, o quadrado de um lado é igual à soma dos
quadrados dos outros dois, menos duas vezes o produto desses dois lados
pelo cosseno do ângulo formado por eles.
|
→PQ|² = |
→ v -
→ u |² = |
→ v |² + |
→ u |² - 2.|
→ v |.|
→ u |.cosθ
(II) No Plano
[(x
v.x
u)
+ (y
v.y
u) + (z
v.z
u)] = |
→ v |.|
→ u |.cosθ
(I) e (II)
Produto Escalar:
→ v .→ u = [(xv.xu)
+ (yv.yu) + (zv.zu)] =
|
0 se → v = 0 ou → u = 0 |
|→ v |.|→ u |.cosθ |
O produto escalar de dois vetores
é a soma dos produtos
entre as respectivas coordenadas de cada um é também igual ao produtos
de ambos módulos pelo cosseno entre eles.
|
→ v |, |
→ u
| e cosθ sendo CONSTANTE no espaço, variando apenas a posição do
conjunto, as projeções de ambos variam, porém, o produto escalar é o
mesmo.
A soma de dois vetores e a diferença de dois vetores são as diagonais
do paralelogramo formado pelos dois vetores.
Também utiliza-se a notação
→ v ×
→ u para → v .
→ u
Demonstração
Será considerado nula as coordenadas do eixo-z para facilitar o desenho.
cos60º = 0,5 | sen60º = 0,866 | cos30º = 0,866 | sen30º = 0,5

Dados:
cos60º = 10/v= 0,5 => v = 20
sen60º = vy/20 = 0,866 => vy = 17,32 e vx = 10
sen30º = 15/u = 0,5 => u = 30
cos30º = ux/30 = 0,866 => ux = 25,98
Temos:
20.30.cos30º = 519,6
A soma do produto das respectivas coordenadas é: 17,32 . 15 + 10 .
25,98 = 519,6
7.
Produto Vetorial:
→
v ^→ u ou
→ v ×
→ u
Para dois vetores linearmente independentes,
→ v e
→ u , o módulo do produto vetorial
entre eles é dado por |
→ v ^→ u | que é igual a área do
paralelogramo formado entre os dois conforme figura abaixo.

Caso,
→ v e
→ u fossem linearmente
dependentes, então:
→ v ^→ u =
→ 0
Pela figura abaixo pode-se perceber que as coordenadas de
→ v ^→ u, → v e
→ u
→(v ^→ u) ^ → v =
→ u
→(v ^→ u) ^ → u =
→ v
Utiliza-se o sinal "^" acento circunfléxico para o produto vetorial
diferenciando do sinal "." ponto para o produdo escalar, porém, é comum
utilizar-se o sinal ponto "." para o cálculo de multiplicação dos
versores (
→ i .
→ i =
→ 0 deveria ser
→ i ^
→ i =
→ 0). Também é comum utilizar o sinal
de vez "×".
Obs:
antes de usar a regra da mão direita verifique esta regra no sistema de
coordenadas que você adotou, note que → i ^→ j = → k
no sistema de coordenadas acima o produto vetorial é no sentido
anti-horário.
|
Para uma base ortogonal positiva (
→ i ,
→ j ,
→ k ),
→ v = (x
v,
y
v,
z
v) e
→ u
= (x
u,
y
u,
z
u) o produto vetorial entre ambos pode ser
representado pelo determinande da matriaz abaixo.
A definição do produto vetorial nos permite escrever que:
→ i .
→ i =
→ j .
→ j =
→ k .
→ k =
→ 0
→ i .
→ j =
→ k
→ k .
→ i =
→ j
→ j .
→ k =
→ i ou
→ i ^
→ j =
→ k
→ k ^
→ i =
→ j
→ j ^
→ k =
→ i
Note que as igualdades correspondem a uma permutação circular a partir
da primeira.
→ j .
→ i =
→-k → i .
→ k = -
→ j
→ k .
→ j = -
→ i ou
→ j ^
→ i =
→-k → i ^
→ k = -
→ j
→ k ^
→ j = -
→ i
Note que as igualdades correspondem a uma inversão da ordem dos fatores
em relação às igualdades anteriores.
7.1. Escolha do sistema de Coordenadas
É preciso padronizar o sitema de coordenadas para trabalhar com
geometria analítica. O eixo-x fica na horizontal com sentido positivo
para à esqueda. O eixo-y e o eixo-z deve ser escolhido. Após adotar um
sistema não deve mais alterá-lo.
Para
saber qual é o primeiro vetor do produto vetorial tome como referência
os versores dos eixos (i, j e k) juntamente com o sentido positivo do ângulo.
O observador está olhando para o produto vetorial.
7.2. Produto Vetorial (Matriz)
O produto vetorial é a multiplicação um a um das coordenadas do
primeiro vetor pelas coordenadas do segundo vetor, observe acima como
fica a multiplicação dos versores.
→ v ^→ u = (x
v→. i , y
v.
→ j ,
z
v.
→ k ).(x
u.→ i ,
y
u.
→ j ,
z
u.
→ k ) = x
v.y
u.
→ k - x
v.z
u.
→ j - y
v.x
u.
→ k + y
v.z
u.
→ i + z
v.x
u.
→ j - z
v.y
u.
→ i
O determinante abaixo corresponde a mesma expressão acima.
→ v ^→ u =
→ i |
→ j |
→ k |
xv |
yv |
zv |
xu |
yu |
zu |
Também podemos agrupar a expressão anterior em três parcelas de
determinantes de grau dois.
→ v ^→ u =
yv
zv
yu zu |
→. i +
|
xv zv
xu zu |
→. j +
|
xv yv
xu yu |
→. k |
→ v ^→ u = ( yv.zu
- zv.yu).→ i + ( xv.zu
- zv.xu).→ j + ( xv.yu
- yv.xu).→ k |
O determinante abaixo corresponde a mesma expressão acima.
Matriz 3x3
→ u ^→ v = -
→ i |
→ j |
→ k |
xv |
yv |
zv |
xu |
yu |
zu |
Matriz 2x2
→ u ^→ v = -
yv
zv
yu zu |
→. i -
|
xv zv
xu zu |
→. j -
|
xv yv
xu yu |
→. k |
→ u ^→ v = -( yv.zu
- zv.yu).→ i - ( xv.zu
- zv.xu).→ j - ( xv.yu
- yv.xu).→ k |
→ v ^→ u é um vetor ortogonal
a
→ v e
→ u
( y
v.z
u - z
v.y
u)² + ( x
v.z
u
- z
v.x
u)² + ( x
v.y
u
- y
v.x
u)² =
→ v ^→ u =
→ w
(
→ v ^→ u ) .
→ v = |
→ w |.|
→ v |.cosθ
cosθ = 1 => θ = 90º
Regra da Mão Direita
Obs:
- Olhando o produto vetorial de frente (figura acima) primeiro vetor é
→ v do produto vetorial
→ v ^→ u , ou seja, a multiplicação é
feita no sentido anti-horário.
- Para o produto vetorial
→
u ^
→ v , o
primeiro vetor é
→ u
e a multiplicação é feita no sentido horário. Terá sentido oposto ao
protudo vetorial
→ v ^→ u .
8. Direção de Visualização
Cálculo do ângulo de visualização através do produto escalar:
Expressão cartesiana do produto escalar: OP•N = |OP|*|N|*cos(ângulo)
Expressão analítica do produto escalar: OP•N = OP.x * N.x
+ OP.y * N.y + OP.z * N.z
Conforme figura abaixo OP é o vetor (O -P2) e N é o vetor ('O - P2).
O produto escalar OA•N é Positivo para um polígono de face traseira
(vetores com ângulo menor que 90º, face virada para trás, não visível)
Negativo para um polígono de face frontal (vetores com ângulo maior
que
90º, face virada para a frente) Igual a zero para um polígono de face
"lateral" (vetores perpendiculares, face não visível)
Produto Escalar:
→ v .→ u = [(xv.xu)
+ (yv.yu) + (zv.zu)] =
|
0 se → v = 0 ou → u = 0 |
|→ v |.|→ u |.cosθ |
Produto Vetorial
→ v ^→ u = (xv→. i , yv.→ j ,
zv.→ k ).(xu.→ i , yu.→ j ,
zu.→ k ) = xv.yu.→ k - xv.zu.→ j - yv.xu.→ k + yv.zu.→ i + zv.xu.→ j - zv.yu.→ i
|
A face de trás tem a distância de seus
vértices até o observado maior que a face que fica na frente.
A visibilidade inicial é de acordo com a posição do observador, ou
seja, é mais fácil posicionar o objeto com rotação zero (0º) nos três
eixos do que calcular tais ângulos para o posicionamento do observador.
A direção de observação fará um ângulo com o produto vetorial. O
produto vetorial é perpendicular a face cuja arestas o originou.
O olho do observador corresponde ao ponto O. O observador olha para o
ponto P2
ox=x5; oy=-500;oz=z5;
fx=x5; fy=y5;fz=z5;
Observações:
Estudo dos Sinais
O PONTO QUE TEM A
COORDENADA-Z MAIOR É O PONTO OCULTO. Ou também quando a coordenada-z do
produto vetorial 2 for negativa (conforme teste realizado)
(P3-P2)^(P6-P2)
1º) No sistema acima o produto vetorial (P3-P2)^(P6-P2), o primeiro
vetor pelo segundo vetor é no sentido
anti-horário, note que pelo
sistema o primeiro versor pelo segundo é no sentido horário
→ i ^→ j = → k,
OS VERSORES SERVEM DE REFERÂNCIA PARA SABER QUAL VETOR É O PRIMEIRO NO
PRODUTO VETORIAL, LEMBRANDO QUE A INVERSÃO DE MULTIPLICAÇÃO DOS DOIS
VETORES INVERTERÁ TAMBÉM O SENTIDO DO PRODUTO VETORIAL. O sistema de
coordenadas é adotado, porém é a referência para o produto vetorial.
2°) As faces e arestas que ficam na frente do observador ficarão atrás
no plano de projeção, ou seja, o inverso, o ponto mais próximo do
obervador é o mais longe do plano de observação.
3º) A projeção 3D é feita com as coordenadas do eixo-x e as
coordenadas do eixo-y, porque a tela do monitor não possui o eixo-z.
4°) A direção de visiblidade é contraria a direção de "projeção" do
objeto no plano de visão, logicamente o plano de visão tem de estar
entre o observador e o objeto.
5º)
O vetor de observação tem origem no ponto observado (P2) e extremidade no ponto de observação (O).
O: ponto
corresponde ao
olho do observvador,
este ponto se encontra parado.
θ1: é o ângulo entre o vetor
normal à face considerada e a direção de observação do
ponto considerado (P1),
o ângulo de observação de um ponto forma um ângulo de visão máxima de
90º à direita e 90º à esquerda da reta normal N. No detalhe no canto
inferior direito da figura acima podemos perceber que à medida que o
ponto de obserrvação O
for
abrindo e girando em torno de N, quando atingir os 90º o círculo
formado estará no mesmo plano da face considerada. Portanto, o ângulo
de visão máxima é 90º com a direção do observador e mais 90º do outro
lado da reta normal com o plano da face considerada.
θ1: determina a visibilidade de
três faces e a invisibilitas das faces opostas.
6º) O ponto P2 da figura corresponde ao ponto 2 do cubo padrão, o ponto
P3 da figura corresponde ao ponto 3 do cubo padrão, o ponto P6 da
figura corresponde ao ponto 6 do cubo padrão.
7º) O ângulo de 90º formado entre a face considerada e a normal a ela
pertence a um plano fixo. O ângulo
θ1
formado entre a normal e a direção do observador pode fazer um giro em
torno da reta normal conforme detalhe no canto inferior direito da
figura acima, ou seja, o ponto
O
pode girar 360º em torno da reta normal com o mesmo ângulo
θ1.
8º) O campo
de visão é 90º para um lado e 90º para o outro lado da direção de visão.
- Se uma face é visível, a face oposta paralela é invisível e vice
versa, com excecão é claro da face perpendicular a direção de visão que
é a única face visível.
9º) O ângulo de observação de um ponto é formado pela parcela de 90º
correspondente ao produto vetorial (normal) com o plano da face
mais o ângulo
θ1 formado
entre o produto vetorial (normal) e a
direção de observação. Portanto
θ1 pode ter no máximo 90º.
10º) Considera-se o objeto opaco. Apenas a superfície é visível.
11º) Embora o ser humano tenha dois olhos, as distância entre os dois é
tanto mais desprezada quanto maior é a distância do objeto ao
observador.
12º) O foco da visão é apenas um ponto, o outro olho que não faz o foco
a
imagem aparece ofuscada.
13º) A imagem observada é considerada com apenas um olho.
14º) O campo de visão é um plano perpendicular a direção da visão, será
visível todos os pontos do objeto que se projetarem perpendicularmente
no plano de visão sem interseccionar o objeto.
15º) Pontos visíveis estão voltados para o plano de visão, ou seja, a
reta
nornal (produto vetorial) fura o plano de visão.
16º) Determinado o ponto de observação, a direção de observação de um
ponto formará três ângulo, um com cada nornal a face visível.
17º)
Para não complicar ainda mais não será utilizado o método scale(1,-1)
porque ao utilizá-lo o sentido de giro padrão passa a ser
horário.
18º) Cubo padrão adotado:

vértice 0(-1,1,-1)
vértice 1(1,1,-1)
vértice 2(1,1,1)
vértice 3(-1,1,1)
vértice 4(-1,-1,-1)
vértice 5(1,-1,-1)
vértice 6(1,-1,1)
vértice 7(-1,-1,1)
faces.push([t[0],t[1],t[2],t[3]]);//face 0
faces.push([t[1],t[5],t[4],t[0]]);//face 1
faces.push([t[2],t[6],t[5],t[1]]);//face 2
faces.push([t[3],t[2],t[6],t[7]]);//face 3
faces.push([t[4],t[0],t[3],t[7]]);//face 4
faces.push([t[5],t[6],t[7],t[4]]);//face 5
9. Produto Escalar
Devemos achar o ângulo entre o produto vetoria (normal a face) e a
direção do observador. Isso pode ser feito com a fórmula do produto
escalar entre o produto vetorial (normal a face) e a direção do
obserrvador.
(
→ i ,
→ j ,
→ k)
(
→ i ) = (1,0,0)
(
→ j ) = (0,1,0)
(
→ k) = (0,0,1)
→ v = (x
v, y
v,
z
v)
→ u = (x
u, y
u,
z
u)
Fórmula:
→ v .
→ u =
[(x
v.x
u)
+ (y
v.y
u) + (z
v.z
u)] = |
→ v |.|
→ u |.cosθ
- Ponto de Observação
Para um ponto representado por um vértice v = (x
v, y
v,
z
v) e o olho do observador posicionado no ponto Ob = (x
ob,
y
ob,
z
ob) teremos o seguinte vetor de observação:
→Ob = (x
ob - x
v,
y
ob - y
v, z
ob - z
v)
|
→Ob| =√
(xob - xv )²
+ (yob - yv)+ (zob - zv )²
→ v .
→ Ob =
[(x
v.x
ob)
+ (y
v.y
ob) + (z
v.z
ob)] = |
→ v |.|
→Ob|.cosθ
cosθ = [(x
v.x
ob)
+ (y
v.y
ob) + (z
v.z
ob)]/|
→ v |.|
→Ob| => θ = acos([(x
v.x
ob)
+ (y
v.y
ob) + (z
v.z
ob)]/|
→ v |.|
→ob|)
O ângulo entre a normal e a a direção de visibilidade com 0 < θ <
90º a face é visível e a contra face é invisível cuja angulo entre sua
normal e a direção de observação (a mesma) forma ângulo igual a
180º < θ <270º.
9.1. Cálculo do Ângulo entre o Produto
Vetorial e a Direção de Visualização
Serão feitas algumas alterações no primeiro código.
Produto Vetorial
Para encontrar a reta normal a face basta achar o produto vetorial no
vértice foco da observação. Será utilizado a subtração de pontos
(vértices) para encontrar os dois vetores que formam o plano da face.
Fórmula:
v^u=yv.zu-zv.yu,xv.zu-zv.xu,xv.yu-yv.xu
ou
Fórmula:
v1^v2=yv1.zv2-zv1.yv2,zv1.xv2-xv1.zv2,xv1.yv2-yv1.xv2
Produto Vetorial 1: P1-P5^P6-P5:
v1=[t[1].x-t[5].x,t[1].y-t[5].y,t[1].z-t[5].z];
v2=[t[6].x-t[5].x,t[6].y-t[5].y,t[6].z-t[5].z];
produto1=[(v1[1]*v2[2])-(v1[2]*v2[1]),(v1[2]*v2[0])-(v1[0]*v2[2]),(v1[0]*v2[1])-(v1[1]*v2[0])];//
face visível e face oculta
Produto Vetorial 2: P6-P5^P4-P5"
v3=[t[6].x-t[5].x,t[6].y-t[5].y,t[6].z-t[5].z];
v4=[t[4].x-t[5].x,t[4].y-t[5].y,t[4].z-t[5].z];
produto2=[(v3[1]*v4[2])-(v3[2]*v4[1]),(v3[2]*v4[0])-(v3[0]*v4[2]),(v3[0]*v4[1])-(v3[1]*v4[0])];
Direção de Visualização:
fx=x5; fy=y5; fz=z5;
ox=x5; oy=-500; oz=z5;
var ob= Math.sqrt(Math.pow(ox-x5, 2)+Math.pow(oy-y5, 2)+Math.pow(oz-z5,
2));
Módulo do Produto Vetorial 1:
var prod1 = Math.sqrt(Math.pow(produto1[0], 2)+Math.pow(produto1[1],
2)+Math.pow(produto1[2], 2));
Módulo do Produto Escalar 1:
var cartesiano1 = (produto1[0]*(ox-fx)) + (produto1[1]*(oy-fy))
+(produto1[2]*(oz-fz));
a2 = Math.acos(cartesiano1/(prod1*ob));
a2=180*a2/Math.PI;
Módulo do Produto Vetorial 2:
var prod2 = Math.sqrt(Math.pow(produto2[0], 2)+Math.pow(produto2[1],
2)+Math.pow(produto2[2], 2));
Módulo do Produto Escalar 2:
var cartesiano2 = (produto2[0]*(ox-fx)) + (produto2[1]*(oy-fy))
+(produto2[2]*(oz-fz));
a3 = Math.acos(cartesiano2/(prod2*ob));
a3=180*a3/Math.PI;
Observações:
Math.pow(base, expoente) = base
expoente
Math.sqrt(número)=
2√
numero
Math.acos(número) = aco-cosseno, é o ângulo em radiano do
cosseno, cos(angulo) = numero => acos(numero) = angulo
Desenho do Produto Vetorial e da Direção de Visão:
ctx.beginPath();
ctx.moveTo(t[5].x,t[5].y);
// produto1: P5 é o início do vetor Produto Vetorial
ctx.lineTo(produto1[0]+t[5].x,produto1[1]+t[5].y);
// o ponto de extremidade é igual ao módulo (coordenada) mais o ponto de início (P5).
ctx.moveTo(t[5].x,t[5].y);
// produto1: P5 é o início do vetor Produto Vetorial
ctx.lineTo(produto2[0]+t[5].x,produto2[1]+t[5].y);
// o ponto de extremidade é igual ao módulo (coordenada) mais o ponto de início (P5).
ctx.moveTo(x5,y5);
// direcao vista (escolhido)
ctx.lineTo(ox,oy);
ctx.stroke();
ctx.closePath();
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="c" width="601" height="601" style="border:1px solid #000000;">
O seu browser não suporta o elemento canvas do HTML5.
Por favor, actualize o seu browser.
</canvas><br>
<button onclick="faz()">Ok</button><br>
<script>
var c_canvas = document.getElementById("c");
var ctx = c_canvas.getContext("2d");
function Point3D(x,y,z) {
this.x = x;
//"this.x =x significa que a variável global x (não declarada até
então) é igual ao "
this.y = y; //parametro x, o parâmtro x poderia ter outro nome
this.z = z;
this.rotateZ = function(angle) {// giro do objeto no sentido
anti-horario para os tres eixos
var rad, cosa, sina, x, y;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = this.x*cosa-this.y*sina; //"x é uma nova variável interna e this.x
é a variável x global"
y = this.x*sina+this.y*cosa;
return new Point3D(x, y,this.z); // entrada de novos parametros, em vez
de this.z poderia ser
}
//"apenas z (this.z = z), mas this.z se refere a variável
global
z"
this.rotateX = function(angle) {
var rad, cosa, sina, y, z;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = this.y*cosa-this.z*sina;
z = this.y*sina+this.z*cosa;
return new Point3D(this.x, y, z);
}
this.rotateY = function(angle) {
var rad, cosa, sina, z, x;
rad = angle*Math.PI/180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = this.z*cosa-this.x*sina;
x = this.z*sina+this.x*cosa;
return new Point3D(x,this.y, z);
}
this.translate = function(tx,ty,tz) {
return new Point3D(x + tx,y + ty,z + tz)
}
}
var xc = Math.ceil((601-1)/2);
var yc = Math.ceil((601-1)/2);
var zc = Math.ceil((601-1)/2); //"zc no lado positivo do eixo z"
var w = 100;
var h = 100;
var dp = 100;
var xo = (xc - w/2);
var yo = (yc + h/2);
var zo = (zc - dp/2);
var x1 = (xc + w/2);
var y1 = (yc + h/2);
var z1 = (zc - dp/2);
var x2 = (xc + w/2);
var y2 = (yc + h/2);
var z2 = (zc + dp/2);
var x3 = (xc - w/2);
var y3 = (yc + h/2);
var z3 = (zc + dp/2);
var x4 = (xc - w/2);
var y4 = (yc - h/2);
var z4 = (zc - dp/2);
var x5 = (xc + w/2);
var y5 = (yc - h/2);
var z5 = (zc - dp/2);
var x6 = (xc + w/2);
var y6 = (yc - h/2);
var z6 = (zc + dp/2);
var x7 = (xc - w/2);
var y7 = (yc - h/2);
var z7 = (zc + dp/2);
var vertices = new Array();
vertices.push(new Point3D(xo, yo, zo));// vertice 0
vertices.push(new Point3D(x1, y1, z1));// vertice 1
vertices.push(new Point3D(x2, y2, z2));// vertice 2
vertices.push(new Point3D(x3, y3, z3));// vertice 3
vertices.push(new Point3D(x4, y4, z4));// vertice 4
vertices.push(new Point3D(x5, y5, z5));// vertice 5
vertices.push(new Point3D(x6, y6, z6));// vertice 6
vertices.push(new Point3D(x7, y7, z7));// vertice 7
var angle2 = -10;
function faz(){
ctx.clearRect(0,0,600,600);
var t = new Array();
angle2 = angle2+10;
if(angle2==360){angle2=0;}
for( var i = 0; i < vertices.length; i++ ) {
var r =
vertices[i].translate(-xc,-yc,-zc).rotateX(20).rotateY(angle2).rotateZ(angle2).translate(xc,yc,zc);
t.push(r);
}
var faces = new Array();
faces.push([t[0],t[1],t[2],t[3]]);//face 0
faces.push([t[4],t[0],t[3],t[7]]);//face 1
faces.push([t[4],t[0],t[1],t[5]]);//face 2
faces.push([t[5],t[1],t[2],t[6]]);//face 3
faces.push([t[2],t[6],t[7],t[3]]);//face 4
faces.push([t[4],t[5],t[6],t[7]]);//face 5
//"v1^v2=yv1.zv2-zv1.yv2,zv1.xv2-xv1.zv2,xv1.yv2-yv1.xv2"
//"P1-P5^P6-P5"
v1=[t[1].x-t[5].x,t[1].y-t[5].y,t[1].z-t[5].z];
v2=[t[6].x-t[5].x,t[6].y-t[5].y,t[6].z-t[5].z];
produto1=[(v1[1]*v2[2])-(v1[2]*v2[1]),(v1[2]*v2[0])-(v1[0]*v2[2]),(v1[0]*v2[1])-(v1[1]*v2[0])];//
face visível e face oculta
//"P6-P5^P4-P5"
v3=[t[6].x-t[5].x,t[6].y-t[5].y,t[6].z-t[5].z];
v4=[t[4].x-t[5].x,t[4].y-t[5].y,t[4].z-t[5].z];
produto2=[(v3[1]*v4[2])-(v3[2]*v4[1]),(v3[2]*v4[0])-(v3[0]*v4[2]),(v3[0]*v4[1])-(v3[1]*v4[0])];
fx=x5; fy=y5; fz=z5;
ox=x5; oy=-500; oz=z5;
var ob= Math.sqrt(Math.pow(ox-x5, 2)+Math.pow(oy-y5, 2)+Math.pow(oz-z5, 2));
var prod1 = Math.sqrt(Math.pow(produto1[0], 2)+Math.pow(produto1[1], 2)+Math.pow(produto1[2], 2));
var cartesiano1 = (produto1[0]*(ox-fx)) + (produto1[1]*(oy-fy)) +(produto1[2]*(oz-fz));
a2 = Math.acos(cartesiano1/(prod1*ob));
a2=180*a2/Math.PI;
var prod2 = Math.sqrt(Math.pow(produto2[0], 2)+Math.pow(produto2[1], 2)+Math.pow(produto2[2], 2));
var cartesiano2 = (produto2[0]*(ox-fx)) + (produto2[1]*(oy-fy)) +(produto2[2]*(oz-fz));
a3 = Math.acos(cartesiano2/(prod2*ob));
a3=180*a3/Math.PI;
document.getElementById("ida").innerHTML=angle2;
zoculto=0;//importantissimo para o inicio da comparacao
for(i=0;i<7;i=i+1){
for(r=0;r<8;r=r+1){
if(t[i].z<t[r].z){ if(t[r].z
>zoculto){zoculto=t[r].z;a=r;}"a é variável que guarda o valor
do índice do ponto oculto"
xoculto= t[a].x;
yoculto= t[a].y;
document.getElementById("idzoculto").innerHTML=zoculto;
document.getElementById("idxoculto").innerHTML=xoculto;
document.getElementById("idyoculto").innerHTML=yoculto;
document.getElementById("idr").innerHTML=a;
}//fecha o se
}//fecha o for interno
switch (a) {
case 0:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[1].x,t[1].y); //face 0
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y); //face1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 1:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[2].x,t[2].y); //face 0
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[2].x,t[2].y); //face3
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 2:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[3].x,t[3].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.stroke();
ctx.closePath();
break;
case 3:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 4:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[5].x,t[5].y); //face 5
ctx.lineTo(t[6].x,t[6].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[3].x,t[3].y); //face 1
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case 5:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[6].x,t[6].y); //face 5
ctx.lineTo(t[7].x,t[7].y);
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[2].x,t[2].y);// face 3
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
case
6:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[7].x,t[7].y); //face 5
ctx.lineTo(t[4].x,t[4].y);
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[3].x,t[3].y);
ctx.lineTo(t[7].x,t[7].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.stroke();
ctx.closePath();
break;
case
7:
ctx.beginPath();
ctx.setLineDash([]);
ctx.lineWidth = 2;
ctx.strokeStyle="#000000";
ctx.font = "normal 18px
Verdana";
ctx.moveTo(t[0].x,t[0].y); //face 0
ctx.lineTo(t[1].x,t[1].y);
ctx.lineTo(t[2].x,t[2].y);
ctx.lineTo(t[3].x,t[3].y);
ctx.lineTo(t[0].x,t[0].y);
ctx.moveTo(t[4].x,t[4].y); //face 5
ctx.lineTo(t[5].x,t[5].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.moveTo(t[0].x,t[0].y); //face 1
ctx.lineTo(t[4].x,t[4].y);
ctx.moveTo(t[1].x,t[1].y); //face3
ctx.lineTo(t[5].x,t[5].y);
ctx.moveTo(t[2].x,t[2].y);
ctx.lineTo(t[6].x,t[6].y);
ctx.stroke();
ctx.closePath();
break;
}//"fecha o caso ou
switch"
}//fecha o for externo
ctx.beginPath();
ctx.moveTo(t[5].x,t[5].y); // produto1
ctx.lineTo(produto1[0]+t[5].x,produto1[1]+t[5].y);
ctx.moveTo(t[5].x,t[5].y); // produto2
ctx.lineTo(produto2[0]+t[5].x,produto2[1]+t[5].y);
ctx.moveTo(x5,y5); // direcao vista
ctx.lineTo(ox,oy);
ctx.stroke();
ctx.closePath();
ctx.fillText("0", t[0].x, t[0].y); //"escrita do pontos nos vertices"
ctx.fillText("1", t[1].x, t[1].y);
ctx.fillText("2", t[2].x, t[2].y);
ctx.fillText("3", t[3].x, t[3].y);
ctx.fillText("4", t[4].x, t[4].y);
ctx.fillText("5", t[5].x, t[5].y);
ctx.fillText("6", t[6].x, t[6].y);
ctx.fillText("7", t[7].x, t[7].y);
Po="xo="+t[0].x.toFixed(4)+" yo="+
t[0].y.toFixed(4)+" zo="+t[0].z.toFixed(4);
//"posição dos pontos"
P1="x1="+t[1].x.toFixed(4)+" y1="+ t[1].y.toFixed(4)+" z1="+t[1].z.toFixed(4);
P2="x2="+t[2].x.toFixed(4)+" y2="+ t[2].y.toFixed(4)+" z2="+t[2].z.toFixed(4);
P3="x3="+t[3].x.toFixed(4)+" y3="+ t[3].y.toFixed(4)+" z3="+t[3].z.toFixed(4);
P4="x4="+t[4].x.toFixed(4)+" y4="+ t[4].y.toFixed(4)+" z4="+t[4].z.toFixed(4);
P5="x5="+t[5].x.toFixed(4)+" y5="+ t[5].y.toFixed(4)+" z4="+t[5].z.toFixed(4);
P6="x6="+t[6].x.toFixed(4)+" y6="+ t[6].y.toFixed(4)+" z6="+t[6].z.toFixed(4);
P7="x7="+t[7].x.toFixed(4)+" y7="+ t[7].y.toFixed(4)+" z7="+t[7].z.toFixed(4);
ctx.fillText("Po=>"+Po,10,400);
ctx.fillText("P1=>"+P1,10,415);
ctx.fillText("P2=>"+P2,10,430);
ctx.fillText("P3=>"+P3,10,445);
ctx.fillText("P4=>"+P4,10,460);
ctx.fillText("P5=>"+P5,10,475);
ctx.fillText("P6=>"+P6,10,490);
ctx.fillText("P7=>"+P7,10,505);
document.getElementById("idob").innerHTML=ob;
document.getElementById("idprod1").innerHTML=prod1;
document.getElementById("idprod2").innerHTML=prod2;
document.getElementById("idcar1").innerHTML=cartesiano1;
document.getElementById("idcar2").innerHTML=cartesiano2;
document.getElementById("ida2").innerHTML=a2;
document.getElementById("ida3").innerHTML=a3;
document.getElementById("z2").innerHTML=produto1[2];
document.getElementById("z3").innerHTML=produto2[2];
a22=(180*Math.atan(4*x5/5*y5))/Math.PI;
document.getElementById("ida").innerHTML=angle2;
}// fecha a funcao faz
</script>
Módulo Observador = <span id="idob"></span><br>
Produto1 = <span id="idprod1"></span><br>
cartesiano1 = <span id="idcar1"></span><br>
Ângulo = <span id="ida2"></span><br>
produto1z = <span id="z2"></span><br>
-----<br>
Produto2 = <span id="idprod2"></span><br>
cartesiano2 = <span id="idcar2"></span><br>
Ângulo = <span id="ida3"></span><br>
produto2z = <span id="z3"></span><br>
-----------<br>
rotação =<span id="ida"></span>º<br>
<br>
Ponto oculto = <span id="idr"></span><br>
Coordenada-Z maior: Zmaior = <span id="idzoculto"></span><br>
Coordenada-X = <span id="idxoculto"></span><br>
Coordenada-Y = <span id="idyoculto"></span><br>
</body>
</html>
Link para execução do
código acima