vidrio ventana una tutomartes tutomarte esfera divierte dibujar dibuja como color arte animales r matlab plot computer-vision

ventana - tutomarte



Cómo dibujar una bola de cristal con partículas de dos colores en el interior (9)

Como la pregunta es

Me pregunto si hay alguna forma de programar con R, matlab o cualquier otro idioma .

y TeX está completo y puede considerarse un lenguaje de programación, tomé algo de tiempo y creé un ejemplo en LaTeX usando TikZ. Como el OP escribe que es para un trabajo de investigación, esto tiene la ventaja de que puede integrarse directamente en el papel, suponiendo que también esté escrito en LaTeX.

Entonces, aquí va:

/documentclass[tikz]{standalone} /usetikzlibrary{positioning, backgrounds} /usepackage{pgf} /pgfmathsetseed{/number/pdfrandomseed} /begin{document} /begin{tikzpicture}[background rectangle/.style={fill=black}, show background rectangle, ] % Definitions /def/ballRadius{5} /def/pointRadius{0.1} /def/nRed{30} /def/nBlue{30} % Draw all red points /foreach /i in {1,...,/nRed} { % Get random coordinates /pgfmathparse{0.9*/ballRadius*rand}/let/mrho/pgfmathresult /pgfmathparse{360*rand}/let/mpsi/pgfmathresult /pgfmathparse{360*rand}/let/mphi/pgfmathresult % Convert to x/y/z /pgfmathparse{/mrho*sin(/mphi)*cos(/mpsi)}/let/mx/pgfmathresult /pgfmathparse{/mrho*sin(/mphi)*sin(/mpsi)}/let/my/pgfmathresult /pgfmathparse{/mrho*cos(/mphi)}/let/mz/pgfmathresult /fill[ball color=blue] (/mz,/mx,/my) circle (/pointRadius); } % Draw all blue points /foreach /i in {1,...,/nBlue} { % Get random coordinates /pgfmathparse{0.9*/ballRadius*rand}/let/mrho/pgfmathresult /pgfmathparse{360*rand}/let/mpsi/pgfmathresult /pgfmathparse{360*rand}/let/mphi/pgfmathresult % Convert to x/y/z /pgfmathparse{/mrho*sin(/mphi)*cos(/mpsi)}/let/mx/pgfmathresult /pgfmathparse{/mrho*sin(/mphi)*sin(/mpsi)}/let/my/pgfmathresult /pgfmathparse{/mrho*cos(/mphi)}/let/mz/pgfmathresult /fill[ball color=red] (/mz,/mx,/my) circle (/pointRadius); } % Draw ball /shade[ball color=blue!10!white,opacity=0.65] (0,0) circle (/ballRadius); /end{tikzpicture} /end{document}

Y el resultado:

Solo estoy lanzando una idea con posibilidad de cerrar. Necesito dibujar una bola de cristal en la cual las partículas rojas y azules se localicen al azar. Supongo que tengo que ir con Photoshop, e incluso intenté hacer la bola en una imagen, pero como esto es para trabajos de investigación y no tiene por qué ser elegante, me pregunto si hay alguna forma de programar con R, Matlab o cualquier otro. otro idioma.


En Javascript con d3.js: http://jsfiddle.net/jjcosare/rggn86aj/6/ o> Ejecutar fragmento de código

Útil para publicar en línea.

var particleChangePerMs = 1000; var particleTotal = 250; var particleSizeInRelationToCircle = 75; var svgWidth = (window.innerWidth > window.innerHeight) ? window.innerHeight : window.innerWidth; var svgHeight = (window.innerHeight > window.innerWidth) ? window.innerWidth : window.innerHeight; var circleX = svgWidth / 2; var circleY = svgHeight / 2; var circleRadius = (circleX / 4) + (circleY / 4); var circleDiameter = circleRadius * 2; var particleX = function() { return Math.floor(Math.random() * circleDiameter) + circleX - circleRadius; }; var particleY = function() { return Math.floor(Math.random() * circleDiameter) + circleY - circleRadius; }; var particleRadius = function() { return circleDiameter / particleSizeInRelationToCircle; }; var particleColorList = [ ''blue'', ''red'' ]; var particleColor = function() { return "url(#" + particleColorList[Math.floor(Math.random() * particleColorList.length)] + "Gradient)"; }; var svg = d3.select("#quantumBall") .append("svg") .attr("width", svgWidth) .attr("height", svgHeight); var blackGradient = svg.append("svg:defs") .append("svg:radialGradient") .attr("id", "blackGradient") .attr("cx", "50%") .attr("cy", "50%") .attr("radius", "90%") blackGradient.append("svg:stop") .attr("offset", "80%") .attr("stop-color", "black") blackGradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "grey") var redGradient = svg.append("svg:defs") .append("svg:linearGradient") .attr("id", "redGradient") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "100%") .attr("y2", "100%") .attr("spreadMethod", "pad"); redGradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "red") .attr("stop-opacity", 1); redGradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "pink") .attr("stop-opacity", 1); var blueGradient = svg.append("svg:defs") .append("svg:linearGradient") .attr("id", "blueGradient") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "100%") .attr("y2", "100%") .attr("spreadMethod", "pad"); blueGradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "blue") .attr("stop-opacity", 1); blueGradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "skyblue") .attr("stop-opacity", 1); svg.append("circle") .attr("r", circleRadius) .attr("cx", circleX) .attr("cy", circleY) .attr("fill", "url(#blackGradient)"); function isParticleInQuantumBall(particle) { var x1 = circleX; var y1 = circleY; var r1 = circleRadius; var x0 = particle.x; var y0 = particle.y; var r0 = particle.radius; return Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) < (r1 - r0); }; function randomizedParticles() { d3.selectAll("svg > .particle").remove(); var particle = {}; particle.radius = particleRadius(); for (var i = 0; i < particleTotal;) { particle.x = particleX(); particle.y = particleY(); particle.color = particleColor(); if (isParticleInQuantumBall(particle)) { svg.append("circle") .attr("class", "particle") .attr("cx", particle.x) .attr("cy", particle.y) .attr("r", particle.radius) .attr("fill", particle.color); i++; } } } setInterval(randomizedParticles, particleChangePerMs);

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="quantumBall"></div>


En R puede usar la función rasterImage para agregar a un gráfico actual, puede crear / descargar una imagen agradable de una bola de cristal y cargarla en R (vea png, EBImage u otros paquetes) y luego hacerla semitransparente y usa rasterImage para agregarlo al gráfico actual. Probablemente trazaré tus 2 puntos de color primero, luego haré la imagen de la pelota sobre la parte superior (con transparencia, seguirán siendo visibles y se verán como si estuvieran adentro).

Un enfoque más simple (aunque probablemente no tan atractivo) es dibujar un círculo gris semitransparente utilizando la función de polygon para representar la pelota.

Si desea hacer esto en 3 dimensiones y luego mirar el paquete rgl, aquí hay un ejemplo básico:

library(rgl) open3d() spheres3d(0,0,0, radius=1, color=''lightgrey'', alpha=0.2) spheres3d(c(.3,-.3),c(-.2,.4),c(.1,.2), color=c(''red'',''blue''), alpha=1, radius=0.15)


Esto es muy similar a la respuesta de Ben Bolker, pero estoy demostrando cómo se puede agregar un poco de aura a la bola de cristal usando algo de color místico:

library(rgl) lapply(seq(0.01, 1, by=0.01), function(x) rgl.spheres(0,0,0, rad=1.1*x, alpha=.01, col=colorRampPalette(c("orange","blue"))(100)[100*x])) rgl.spheres(0,0,0, radius=1.11, col="red", alpha=.1) rgl.spheres(0,0,0, radius=1.12, col="black", alpha=.1) rgl.spheres(0,0,0, radius=1.13, col="white", alpha=.1) xyz <- matrix(rnorm(3*100), ncol=3) xyz <- xyz * runif(100)^(1/3) / sqrt(rowSums(xyz^2)) rgl.spheres(xyz[1:50,], rad=.02, col="blue") rgl.spheres(xyz[51:100,], rad=.02, col="red") rgl.bg(col="black") rgl.viewpoint(zoom=.75) rgl.snapshot("crystalball.png")

La única diferencia entre los dos está en la lapply solicitud. Puedes ver que con solo cambiar los colores en colorRampPalette puedes cambiar significativamente el aspecto de la bola de cristal. El de la izquierda usa el código de aplicación anterior, el de la derecha usa esto en su lugar:

lapply(seq(0.01, 1, by=0.01), function(x) rgl.spheres(0,0,0,rad=1.1*x, alpha=.01, col=colorRampPalette(c("orange","yellow"))(100)[100*x])) ...code from above

Aquí hay un enfoque diferente donde puedes definir tu propio archivo de textura y usarlo para colorear la bola de cristal:

# create a texture file, get as creative as you want: png("texture.png") x <- seq(1,870) y <- seq(1,610) z <- matrix(rnorm(870*610), nrow=870) z <- t(apply(z,1,cumsum))/100 # Swirly texture options: # Use the Simon O''Hanlon''s roll function from this answer: # http://.com/questions/18791212/equivalent-to-numpy-roll-in-r/18791252#18791252 # roll <- function( x , n ){ # if( n == 0 ) # return( x ) # c( tail(x,n) , head(x,-n) ) # } # One option # z <- mapply(function(x,y) roll(z[,x], y), x = 1:ncol(z), y=1:ncol(z)) # # Another option # z <- mapply(function(x,y) roll(z[,x], y), x = 1:ncol(z), y=rep(c(1:50,51:2), 10))[1:870, 1:610] # # One more # z <- mapply(function(x,y) roll(z[,x], y), x = 1:ncol(z), y=rep(seq(0, 100, by=10), each=5))[1:870, 1:610] par(mar=c(0,0,0,0)) image(x, y, z, col = colorRampPalette(c("cyan","black"))(100), axes = FALSE) dev.off() xyz <- matrix(rnorm(3*100), ncol=3) xyz <- xyz * runif(100)^(1/3) / sqrt(rowSums(xyz^2)) rgl.spheres(xyz[1:50,], rad=.02, col="blue") rgl.spheres(xyz[51:100,], rad=.02, col="red") rgl.spheres(0,0,0, rad=1.1, texture="texture.png", alpha=0.4, back="cull") rgl.viewpoint(phi=90, zoom=.75) # change the view if need be rgl.bg(color="black")

!

La primera imagen en la parte superior izquierda es lo que obtienes si solo ejecutas el código anterior, los otros tres son los resultados de usar las diferentes opciones en el código comentado.


Otra solución con Matlab.

[x,y,z] = sphere(50); [img] = imread(''crystal.jpg''); figure(''Color'',[0 0 0]); surf(x,y,z,img,''edgeColor'',''none'',''FaceAlpha'',.6,''FaceColor'',''texturemap'') hold on; i = 0; while i<100 px = randn(); py = randn(); pz = randn(); d = pdist([0 0 0; px py pz],''euclidean''); if d<1 if mod(i,2)==0 scatter3(px, py, pz,30,''ro'',''filled''); else scatter3(px, py, pz,30,''bo'',''filled''); end i = i+1; end end hold off; camlight; axis equal; axis off;

Salida:


Te recomendaría que povray un vistazo a un programa de rastreo de rayos , por ejemplo, povray . No sé mucho del idioma, pero jugueteando con algunos ejemplos me las arreglé para producir esto sin demasiado esfuerzo.

background { color rgb <1,1,1,1> } #include "colors.inc" #include "glass.inc" #declare R = 3; #declare Rs = 0.05; #declare Rd = R - Rs ; camera {location <1, 10 ,1> right <0, 4/3, 0> up <0,0.1,1> look_at <0.0 , 0.0 , 0.0>} light_source { z*10000 White } light_source{<15,25,-25> color rgb <1,1,1> } #declare T_05 = texture { pigment { color Clear } finish { F_Glass1 } } #declare Ball = sphere { <0,0,0>, R pigment { rgbf <0.75,0.8,1,0.9> } // A blue-tinted glass finish { phong 0.5 phong_size 40 // A highlight reflection 0.2 // Glass reflects a bit } interior{ior 1.5} } #declare redsphere = sphere { <0,0,0>, Rs pigment{color Red} texture { T_05 } interior { I_Glass4 fade_color Col_Red_01 }} #declare bluesphere = sphere { <0,0,0>, Rs pigment{color Blue} texture { T_05 } interior { I_Glass4 fade_color Col_Blue_01 }} object{ Ball } #declare Rnd_1 = seed (123); #for (Cntr, 0, 200) #declare rr = Rd* rand( Rnd_1); #declare theta = -pi/2 + pi * rand( Rnd_1); #declare phi = -pi+2*pi* rand( Rnd_1); #declare xx = rr * cos(theta) * cos(phi); #declare yy = rr * cos(theta) * sin(phi); #declare zz = rr * sin(theta) ; object{ bluesphere translate <xx , yy , zz > } #declare rr = Rd* rand( Rnd_1); #declare theta = -pi/2 + pi * rand( Rnd_1); #declare phi = -pi+2*pi* rand( Rnd_1); #declare xx = rr * cos(theta) * cos(phi); #declare yy = rr * cos(theta) * sin(phi); #declare zz = rr * sin(theta) ; object{ redsphere translate <xx , yy , zz > } #end


Tuve que generar algo tan brillante como la respuesta R en Matlab :) Así que, aquí está mi solución tardía, demasiado complicada y super lenta, pero es bonita ¿no? :)

figure(1), clf, hold on whitebg(''k'') light(... ''Color'',''w'',... ''Position'',[-3 -1 0],... ''Style'',''infinite'') colormap cool brighten(0.2) [x,y,z] = sphere(50); surf(x,y,z); lighting phong alpha(.2) shading interp grid off blues = 2*rand(15,3)-1; reds = 2*rand(15,3)-1; R = linspace(0.001, 0.02, 20); done = false; while ~done indsB = sum(blues.^2,2)>1-0.02; if any(indsB) done = false; blues(indsB,:) = 2*rand(sum(indsB),3)-1; else done = true; end indsR = sum( reds.^2,2)>1-0.02; if any(indsR) done = false; reds(indsR,:) = 2*rand(sum(indsR),3)-1; else done = done && true; end end nR = numel(R); [x,y,z] = sphere(15); for ii = 1:size(blues,1) for jj = 1:nR surf(x*R(jj)-blues(ii,1), y*R(jj)-blues(ii,2), z*R(jj)-blues(ii,3), ... ''edgecolor'', ''none'', ... ''facecolor'', [1-jj/nR 1-jj/nR 1],... ''facealpha'', exp(-(jj-1)/5)); end end nR = numel(R); [x,y,z] = sphere(15); for ii = 1:size(reds,1) for jj = 1:nR surf(x*R(jj)-reds(ii,1), y*R(jj)-reds(ii,2), z*R(jj)-reds(ii,3), ... ''edgecolor'', ''none'', ... ''facecolor'', [1 1-jj/nR 1-jj/nR],... ''facealpha'', exp(-(jj-1)/5)); end end set(findobj(gca,''type'',''surface''),... ''FaceLighting'',''phong'',... ''SpecularStrength'',1,... ''DiffuseStrength'',0.6,... ''AmbientStrength'',0.9,... ''SpecularExponent'',200,... ''SpecularColorReflectance'',0.4 ,... ''BackFaceLighting'',''lit''); axis equal view(30,60)


Un poco tarde en el juego, pero aquí hay un código de Matlab que implementa scatter3sph (desde FEX)

figure(''Color'', [0.04 0.15 0.4]); nos = 11; % number small of spheres S= 3; %small spheres sizes Grid_Size=256; %Coordinates X= Grid_Size*(0.5+rand(2*nos,1)); Y= Grid_Size*(0.5+rand(2*nos,1)); Z= Grid_Size*(0.5+rand(2*nos,1)); %Small spheres colors: (Red & Blue) C= ones(nos,1)*[0 0 1]; C= [C;ones(nos,1)*[1 0 0]]; % Plot big Sphere scatter3sph(Grid_Size,Grid_Size,Grid_Size,''size'',220,''color'',[0.9 0.9 0.9]); hold on light(''Position'',[0 0 0],''Style'',''local''); alpha(0.45); material shiny % Plot small spheres scatter3sph(X,Y,Z,''size'',S,''color'',C); axis equal; axis tight; grid off view([108 -42]); set(gca,''Visible'',''off'') set(gca,''color'',''none'')


En R, usando el paquete rgl (interfaz R-to-OpenGL):

library(rgl) n <- 100 set.seed(101) randcoord <- function(n=100,r=1) { d <- data.frame(rho=runif(n)*r,phi=runif(n)*2*pi,psi=runif(n)*2*pi) with(d,data.frame(x=rho*sin(phi)*cos(psi), y=rho*sin(phi)*sin(psi), z=rho*cos(phi))) } ## http://en.wikipedia.org/wiki/List_of_common_coordinate_transformations with(randcoord(50,r=0.95),spheres3d(x,y,z,radius=0.02,col="red")) with(randcoord(50,r=0.95),spheres3d(x,y,z,radius=0.02,col="blue")) spheres3d(0,0,0,radius=1,col="white",alpha=0.5,shininess=128) rgl.bg(col="black") rgl.snapshot("crystalball.png")