package puzzle.puzzleClasses; import java.awt.BorderLayout; import java.awt.Checkbox; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Font; import java.awt.GridLayout; import java.util.Hashtable; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JRadioButton; import javax.swing.JSlider; import javax.swing.JToggleButton; import jv.geom.PgElementSet; import jv.object.PsPanel; import jv.project.PvDisplayIf; import jv.vecmath.PdVector; public class Metodos { static double Pi = Math.PI; /**Cor que tem de coordenadas em RGB (r,g,b).*/ public static Color corRGB(int r,int g,int b){ float rr=(float)(((double)r)/255);float gg=(float)(((double)g)/255);float bb=(float)(((double)b)/255); Color cor = new Color(rr,gg,bb); return cor; } /**Função que transforma um string num boolean ***/ static Boolean stringToBool(String a){ Boolean aa=new Boolean(a); return aa; } /**Indica se dois números são iguais a menos de um erro eps, se a=b.*/ static boolean numIguais(double a,double b,double eps){ boolean iguais = false; if(Math.abs(a-b)<=eps){ iguais = true; } return iguais; } static boolean vectIguais(PdVector a,PdVector b,double eps){ boolean[] iguais = new boolean[(int) a.getSize()]; boolean ig = false; for(int i=0;i {3, pp}]}, dsp, PlotRange -> {{-3, 3}, {-20, 0}, {-1.2, 1.2}}, Boxed -> False, Axes -> Null, opts]; */ /**Método para transformar um rectângulo num cilindro (se tor=0) ou num toro (se tor=1).*/ static void rectCil(PgElementSet cilindro,double m_a,int tor,double larg,double raio,int numXLine,int numYLine,boolean mostraFaces,boolean mostraArestas){ double u1 = 2*(m_a-1)*Pi, u2 = 2*Pi*m_a, t1 = -larg, t2 = larg; double[] ang = {u1,u2}, compr = {t1,t2}; cilindro.setNumVertices(numXLine*numYLine); int indV = 0; for(int k=0;kPi){ x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(t+Pi+bb); y = 16*Math.sin(uu); }else { x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(uu)*Math.cos(t+bb); y = 16*Math.sin(uu)+a*Raio*(1-Math.cos(uu)/b)*Math.sin(uu)*Math.cos(t+bb); } z = a*Raio*(1-Math.cos(uu)/b)*Math.sin(t+bb); v = new PdVector(x+12*Pi,y+32*Pi,z-2*raio*Pi); linha.setVertex(ind,somaVect(v,transl));ind++; } } naoLinha = false;i=4; } } if(naoLinha){ for(int l=0;l<2*numYLine;l++){ linha.setVertex(l,new PdVector(0,0,0));ind++; } } linha.makeQuadrConn(2,numYLine); linha.setVisible(!naoLinha); linha.showEdges(true); linha.showElements(true); linha.showVertices(false); linha.setGlobalEdgeSize(Puzzle3D.sizeLinhaDiv); linha.setGlobalEdgeColor(Color.yellow); linha.showSmoothElementColors(true); linha.showSmoothLighting(true); linha.showElementBackColors(false); linha.update(linha); } /**Calcular o vector normal a cada face.*/ static PdVector vNormal(PdVector[] vert,PdVector ptoInterior){ PdVector normal; PdVector u = uv(vert[0],vert[1]); PdVector v = uv(vert[1],vert[2]); PdVector vectInt = uv(ptoInterior,vert[0]); PdVector c = cross(u,v); if(produtoEscalar(vectInt,c)>=0){ normal = uni(c); }else { normal = uni(cross(uv(vert[2],vert[1]),uv(vert[1],vert[0]))); } return normal; } /*static void rectCilToro(PgElementSet[] cilindro,PgElementSet[] facesFig,int valorM,int valorN,double m_a,double raio,double Raio,int numXLine,int numYLine){ double m_aa; double t1; double t2; double larg = 2*Pi; if(m_a<=0.5){ m_aa = 2*m_a; t1 = -larg; t2 = 0; }else { m_aa = 2*m_a-1; t1 = 0; t2 = larg; } double u1 = 2*(m_aa-1)*Pi; double u2 = 2*Pi*m_aa; double[] ang = {u1,u1}; double uDelta = (u2-u1)/valorM; double[] compr = {t1,t1}; double tDelta = (t2-t1)/valorN; int ind = 0; for(int i=0;iPi){ x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(t+Pi+bb); y = 16*Math.sin(uu); }else { x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(uu)*Math.cos(t+bb); y = 16*Math.sin(uu)+a*Raio*(1-Math.cos(uu)/b)*Math.sin(uu)*Math.cos(t+bb); } z = a*Raio*(1-Math.cos(uu)/b)*Math.sin(t+bb); v = new PdVector(x+m_aa*12*Pi,y+m_aa*32*Pi,z-4*Pi); } cilindro.setVertex(indV,somaVect(v,transl)); indV++; } } cilindro.makeQuadrConn(numXLine,numYLine); } cilindro.showElements(mostraFaces); cilindro.showEdges(mostraArestas); cilindro.showSmoothElementColors(true); cilindro.showSmoothLighting(true); cilindro.showElementBackColors(false); cilindro.update(cilindro); } /**Método para transformar as partes de um rectângulo nas correspondentes de um cilindro e depois nas correspondentes de uma garrafa de klein.*/ static void rectCilGKs(PvDisplayIf ab,PdVector trans,PdVector dir,PgElementSet[] cilindro,PdVector[] normal,PgElementSet[] facesFig,double valorM,double valorN,double m_a,double raio,double Raio,int numXLine,int numYLine,boolean update){ double m_aa,t1,t2,vM,vN,larg = 2*Pi; if(m_a<=0.5){ m_aa = 2*m_a; t1 = -larg; t2 = 0; vM = valorN; vN = valorM; }else { m_aa = 2*m_a-1; t1 = 0; t2 = larg; vM = valorM; vN = valorN; } double u1 = 2*(m_aa-1)*Pi, u2 = 2*Pi*m_aa, uDelta = (u2-u1)/vM, tDelta = (t2-t1)/vN; double[] ang = {u1,u1}, compr = {t1,t1}; double u; PdVector ptoIntGK = new PdVector(0,0,0); PdVector transl = new PdVector(-13*Pi,-33*Pi,+2*raio*Pi); int ind = 0; for(int i=0;iPi){ x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(t+Pi+bb); y = 16*Math.sin(uu); bx = 6*Math.cos(2*Pi-ang[0])*(1+Math.sin(2*Pi-ang[0])); by = 16*Math.sin(2*Pi-ang[0]); }else { x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(uu)*Math.cos(t+bb); y = 16*Math.sin(uu)+a*Raio*(1-Math.cos(uu)/b)*Math.sin(uu)*Math.cos(t+bb); bx = 6*Math.cos(2*Pi-ang[0])*(1+Math.sin(2*Pi-ang[0])); by = 16*Math.sin(2*Pi-ang[0]); } z = a*Raio*(1-Math.cos(uu)/b)*Math.sin(t+bb); v = new PdVector(x+m_aa*12*Pi,y+m_aa*32*Pi,z-2*raio*Pi); if((1.5*Pi>=ang[0]&&1.5*Pi<=ang[1])){ ptoIntGK = new PdVector(+0,1,0); }else { ptoIntGK = new PdVector(bx+m_aa*12*Pi,by+m_aa*32*Pi,-2*raio*Pi); } } cilindro[ind].setVertex(indV,somaVect(v,transl)); indV++; } } ptoIntGK = somaVect(ptoIntGK,transl); } cilindro[ind].makeQuadrConn(numXLine,numYLine); if(update){cilindro[ind].update(cilindro[ind]); } int nInd = ind; cilindro[ind].showTransparency(true); cilindro[ind].setTransparency(Puzzle3D.transpMin); cilindro[ind].showBoundaries(facesFig[nInd].isShowingBoundaries()); cilindro[ind].setGlobalBndColor(Puzzle3D.corArestas); cilindro[ind].setGlobalBndSize(Puzzle3D.sizeArestas); cilindro[ind].showElements(facesFig[nInd].isShowingElements()); cilindro[ind].showEdges(facesFig[nInd].isShowingEdges()); cilindro[ind].showElementColors(true); cilindro[ind].showSmoothElementColors(true); cilindro[ind].showSmoothLighting(true); cilindro[ind].showElementBackColors(false); cilindro[ind].setGlobalElementColor(facesFig[nInd].getGlobalElementColor()); cilindro[ind].setVisible(facesFig[nInd].isVisible()); PdVector[] vert = {cilindro[ind].getVertex(0),cilindro[ind].getVertex(numYLine-1),cilindro[ind].getVertex(numXLine*numYLine-1-(numYLine-1)),cilindro[ind].getVertex(numXLine*numYLine-1)}; normal[ind] = vNormal(vert,ptoIntGK); //ind++; } //PgPointSet p = new PgPointSet(3); p.setNumVertices(1);p.setVertex(0,new PdVector(0,0,0));ab.addGeometry(p); } } /*static void rectCilGK(PgElementSet[] cilindro,PgElementSet[] facesFig,int valorM,int valorN,double m_a,double raio,double Raio,int numXLine,int numYLine){ double m_aa; double t1; double t2; double larg = 2*Pi; if(m_a<=0.5){ m_aa = 2*m_a; t1 = -larg; t2 = 0; }else { m_aa = 2*m_a-1; t1 = 0; t2 = larg; } double u1 = 2*(m_aa-1)*Pi; double u2 = 2*Pi*m_aa; double[] ang = {u1,u1}; double uDelta = (u2-u1)/valorM; double[] compr = {t1,t1}; double tDelta = (t2-t1)/valorN; int ind = 0; for(int i=0;iPi){ x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(t+Pi+bb); y = 16*Math.sin(uu); }else { x = 6*Math.cos(uu)*(1+Math.sin(uu))+a*Raio*(1-Math.cos(uu)/b)*Math.cos(uu)*Math.cos(t+bb); y = 16*Math.sin(uu)+a*Raio*(1-Math.cos(uu)/b)*Math.sin(uu)*Math.cos(t+bb); } z = a*Raio*(1-Math.cos(uu)/b)*Math.sin(t+bb); v = new PdVector(x+m_aa*12*Pi,y+m_aa*32*Pi,z-4*Pi); } } cilindro[ind].setVertex(indV,v); indV++; } } cilindro[ind].makeQuadrConn(numXLine,numYLine); int nInd = ind; cilindro[ind].showTransparency(true); cilindro[ind].setTransparency(facesFig[nInd].getTransparency()); cilindro[ind].showBoundaries(facesFig[nInd].isShowingBoundaries()); cilindro[ind].setGlobalBndColor(facesFig[nInd].getGlobalBndColor()); cilindro[ind].setGlobalBndSize(facesFig[nInd].getGlobalBndSize()); cilindro[ind].showElements(facesFig[nInd].isShowingElements()); cilindro[ind].showEdges(facesFig[nInd].isShowingEdges()); cilindro[ind].showElementColors(true); cilindro[ind].setGlobalElementColor(facesFig[nInd].getGlobalElementColor()); cilindro[ind].setVisible(facesFig[nInd].isVisible()); cilindro[ind].update(cilindro[ind]); ind++; } } }*/ /**Para construir um cilindro dado as suas extremidades, P e Q, e raio, e dadas o nº de linhas em ambasa as direcções.*/ static void computePartesCilindroNumLines(PgElementSet cilindro,PdVector P,PdVector Q,double raio,int numXLine,int numYLine,double[] ang,double[] compr,Color cor,Color corArestas,double sizeArestas,double transp,boolean mostraFaces,boolean mostraArestas,boolean mostraArestasMesmo,Color corArestasMesmo,double sizeArestasMesmo,boolean visivel){ PdVector PQ = uv(P,Q); PdVector ortog = vectOrtogonal(PQ,1);ortog = uni(ortog); PdVector w = cross(PQ,ortog); w = uni(w); cilindro.setNumVertices(numXLine*numYLine); cilindro.setNumElements(numXLine+1); int ind = 0; for(int i=0;iPi&&u<=2*Pi){ x = bx+rad*Math.cos(v+Pi+bb); y = by; }else { x = bx + rad*Math.cos(u)*Math.cos(v+bb); y = by + rad*Math.sin(u)*Math.cos(v+bb); } z = rad*Math.sin(v+bb); garrafa.setVertex(ind++,x,y,z); } } garrafa.makeQuadrConn(numXLines,numYLines); garrafa.setGlobalElementColor(cor); garrafa.showEdges(mostraArestas); garrafa.showElements(mostraFaces); garrafa.setVisible(visivel); garrafa.showSmoothElementColors(true); garrafa.showSmoothLighting(true); garrafa.showElementBackColors(false); garrafa.update(garrafa); } /**Parametrização da Tira de Mobius (fechada)*/ static void computePartesGarrafaKlein(PgElementSet garrafa,double R,double r,int numXLines,int numYLines,double[] angX,double[] angY,Color cor,Color corArestas,double sizeArestas,double transp,boolean mostraFaces,boolean mostraArestas,boolean visivel){ int ind = 0; double x; double y; double z; double a = (r+R)/(2*R); double b = (-r-R)/(r-R); double ee ; ee = Pi/2;//if(numYLines%2!=0){ee = 0;}else {ee = Pi/2;}//ee = If[OddQ[ppv], 0, 2Pi/(4ppv) // N]; garrafa.setNumVertices(numXLines*numYLines); for (double i=0; iPi&&u<=2*Pi){ x = bx+rad*Math.cos(v+Pi+bb); y = by; z = rad*Math.sin(v+bb); }else { x = bx + rad*Math.cos(u)*Math.cos(v+bb); y = by + rad*Math.sin(u)*Math.cos(v+bb); z = rad*Math.sin(v+bb); } garrafa.setVertex(ind++,x,y,z); } } garrafa.makeQuadrConn(numXLines,numYLines); garrafa.setGlobalElementColor(cor); garrafa.showTransparency(true); garrafa.setTransparency(transp); garrafa.setGlobalElementColor(cor); garrafa.showBoundaries(mostraArestas); garrafa.setGlobalBndColor(corArestas); garrafa.setGlobalBndSize(sizeArestas); garrafa.showEdges(false); garrafa.showElements(mostraFaces); garrafa.setVisible(visivel); garrafa.showSmoothElementColors(true); garrafa.showSmoothLighting(true); garrafa.showElementBackColors(false); garrafa.update(garrafa); } /*......................................................................*/ /*Funções:*/ /**Soma entre dois vectores.*/ static PdVector somaVect(PdVector u,PdVector v){ PdVector soma = new PdVector(u.m_data[0]+v.m_data[0],u.m_data[1]+v.m_data[1],u.m_data[2]+v.m_data[2]); return soma; } /**Diferença entre dois vectores.*/ static PdVector difVect(PdVector u,PdVector v){ PdVector diferença = new PdVector(u.m_data[0]-v.m_data[0],u.m_data[1]-v.m_data[1],u.m_data[2]-v.m_data[2]); return diferença; } /**Determinar um vector, de comprimento r, ortogonal ao vector u*/ static PdVector vectOrtogonal(PdVector u,double r){ PdVector e1 = new PdVector(1,0,0);//Um dos vectores da base canónica PdVector e2 = new PdVector(0,1,0);//Um dos vectores da base canónica PdVector uUni = uni(u); PdVector e; if(Math.abs(produtoEscalar(uUni,e1))>0.95){ e = e2; }else { e = e1; } PdVector vectorOrtogonal = multiVectNum(r,uni(difVect(e,multiVectNum(produtoEscalar(uUni,e),uUni))));//=r*uni(e-(e.u)u) return vectorOrtogonal; } /**Produto entre um número e um vector.*/ /*in[x_, r_:1.] := r^2/x;*/ static PdVector multiVectNum(double u,PdVector v){ PdVector multiplicacao = new PdVector(u*v.m_data[0],u*v.m_data[1],u*v.m_data[2]); return multiplicacao; } /**Verificar se dois vectore são muito parecidos.*/ static boolean iguais(PdVector u,PdVector v,double eps){ boolean saoIguais; if(Math.abs(u.m_data[0]-v.m_data[0])<=eps&&Math.abs(u.m_data[1]-v.m_data[1])<=eps&&Math.abs(u.m_data[2]-v.m_data[2])<=eps){ saoIguais = true; }else { saoIguais = false; } return saoIguais; } /**Vector uv.*/ static PdVector uv(PdVector u,PdVector v){ PdVector uv = new PdVector(-u.m_data[0]+v.m_data[0],-u.m_data[1]+v.m_data[1],-u.m_data[2]+v.m_data[2]); return uv; } /**Produto entre um número e um vector.*/ static PdVector multiNumVect(double u,PdVector v){ PdVector multiplicacao = new PdVector(u*v.m_data[0],u*v.m_data[1],u*v.m_data[2]); return multiplicacao; } /**Produto escalar entre dois vectores*/ /*u.v*/ static double produtoEscalar(PdVector u,PdVector v){ double produto = PdVector.dot(u,v);//= u.m_data[0]*v.m_data[0]+u.m_data[1]*v.m_data[1]+u.m_data[2]*v.m_data[2]; return produto; } /**Produto entre uma matriz e um vector*/ static PdVector produtoMaVect(PdVector[] m,PdVector v){ double x = produtoEscalar(m[0],v); double y = produtoEscalar(m[1],v); double z = produtoEscalar(m[2],v); PdVector produto = new PdVector(x,y,z); return produto; } /**Matriz transposta*/ static PdVector[] transpose(PdVector[] m){ PdVector[] matrizTransp = new PdVector[3]; matrizTransp[0] = new PdVector(m[0].m_data[0],m[1].m_data[0],m[2].m_data[0]); matrizTransp[1] = new PdVector(m[0].m_data[1],m[1].m_data[1],m[2].m_data[1]); matrizTransp[2] = new PdVector(m[0].m_data[2],m[1].m_data[2],m[2].m_data[2]); return matrizTransp; } /**Produto entre duas matrizes, sendo que as suas linhas são os vectores fornecidos*/ static PdVector[] produtoM(PdVector[] m,PdVector[] n){ PdVector[] produto = new PdVector[3]; PdVector[] nT = transpose(n);//Transposta da matriz n. for(int i=0;i<3;i++){ double x = produtoEscalar(m[i],nT[0]); double y = produtoEscalar(m[i],nT[1]); double z = produtoEscalar(m[i],nT[2]); produto[i] = new PdVector(x,y,z); } return produto; } /**ProdutoVectorial entre os vectores u e v.*/ static PdVector cross(PdVector v,PdVector u){ /*double u1 = u.m_data[0]; double u2 = u.m_data[1]; double u3 = u.m_data[2]; double v1 = v.m_data[0]; double v2 = v.m_data[1]; double v3 = v.m_data[2]; double x = u2*v3-v2*u3; double y = u3*v1-v3*u1; double z = u1*v2-v1*u2; PdVector prodExt = new PdVector(x,y,z);*/ PdVector prodExt; prodExt=PdVector.crossNew(v,u); return prodExt; } /**Rotacao um vector u, de um ângulo ang, em torno da recta que passa pela origem e tem como direcção o vector w*/ /*roda "P" do ângulo "t" sobre recta que passa em "A" e tem a direcção de "eixo": ref[w_] :=Module[{vv, uu, ww}, ww = uni[w]; uu = If[Abs[w.{1., 0., 0.}] < Abs[w.{0., 1., 0.}], {1., 0., 0.}, {0., 1.,0.}]; Transpose[{vv = uni[Cross[ww, uu]], Cross[ww, vv], ww}]]; rot[w_, t_] := ref[w].{{Cos[t], Sin[t], 0.}, {-Sin[t], Cos[t], 0.}, {0., 0.,1.}}.Transpose[ref[w]]; rotP[P_, A_, eixo_, ang_] :=(rot[eixo, ang] . (P - A)) + A;*/ static PdVector rotacaoVect(PdVector u,PdVector w,double ang){ PdVector ww = uni(w); PdVector e1 = new PdVector(1.,0.,0.);//Um dos vectores da base canónica PdVector e2 = new PdVector(0.,1.,0.);//Um dos vectores da base canónica PdVector uu; if(Math.abs(produtoEscalar(w,e1))