rgl

2016-09-29 7 views
5

में spheres3d की चिकनीता को कैसे बढ़ाया जाए जब मैं rgl::spheres3d() का उपयोग करता हूं, तो प्रस्तुत किए गए क्षेत्रों में घुटने वाले किनारों वाले किनारे होते हैं।rgl

spheres = data.frame(x = c(1,2,3), y = c(1,3,1), 
        color = c("#992222" , "#222299", "#229922")) 
open3d() 
spheres3d(spheres$x, spheres$y, radius = 1, color = spheres$color) 

enter image description here

स्थापना material3d(smooth = TRUE, line_antialias = TRUE) इस सुधार नहीं होता है। त्रिज्या बढ़ाना या तो मदद नहीं करता है। क्या चिकनीपन को बढ़ाने के लिए कोई तरीका है जिसके साथ वे खींचे जाते हैं?

उत्तर

1

cuttlefish44's excellent answer विस्तार करते हुए, मैं एक parameterization कि बेहतर काम करता है पाया उपयोग करते हुए मेरे दृष्टिकोण है - यानी यह ध्रुवों में कोई दोष हो (छवि में लाइटब्लू क्षेत्र पर काला आर्टिफैक्ट)।

library(rgl) 
sphere.f <- function(x0 = 0, y0 = 0, z0 = 0, r = 1, n = 101, ...){ 
    f <- function(s, t) cbind(r * cos(s) * cos(t) + x0, 
          r * sin(s) * cos(t) + y0, 
          r * sin(t) + z0) 
    persp3d(f, slim = c(0, pi), tlim = c(0, 2*pi), n = n, add = T, ...) 
} 


sphere1.f <- function(x0 = 0, y0 = 0, z0 = 0, r = 1, n = 101, ...){ 
    f <- function(s,t){ 
    cbind( r * cos(t)*cos(s) + x0, 
      r *  sin(s) + y0, 
      r * sin(t)*cos(s) + z0) 
    } 
    persp3d(f, slim = c(-pi/2,pi/2), tlim = c(0, 2*pi), n = n, add = T, ...) 
} 


sphere.f(-1.5,0, col = "lightblue") 
sphere1.f(1.5,0, col = "pink") 

छवि:

enter image description here

+0

यह उत्कृष्ट है - अच्छी नौकरी। एन = 101 पर, भूमध्य रेखा के चारों ओर रिज दोष अभी भी है, लेकिन गति और गुणवत्ता के बीच एक अच्छा समझौता है। एन = 201 के साथ, यह देखना मुश्किल है। एन = 301 पर, मुश्किल से समझदार और अभी भी स्वीकार्य तेज़। – dww

+0

मुझे सही उत्तर वोट देने के लिए धन्यवाद। आरजीएल में कांस्य बैज प्राप्त करना अच्छा लगेगा, लेकिन इस दर पर इसमें लगभग 10 साल लगेंगे। –

2

यह आसान नहीं है; मैं लगता है कि अगर आप इस आप

  • डाउनलोड rgl source from CRAN
  • खोल दे करने के लिए है और संशोधित src/sphereSet.cpp की लाइन 24 है, जो वर्तमान
sphereMesh.setGlobe(16,16); 
है जा रहे हैं क्या करना चाहते हैं

फ़ंक्शन को कुछ बड़े मानों के साथ कॉल करने के लिए (यह फ़ंक्शन src/SphereMesh.cpp की लाइन 25 पर परिभाषित किया गया है; तर्क in_segments ए हैं nd in_sections ...)

  • स्रोत से पैकेज को स्थापित/स्थापित करें; इससे न केवल मानक संकलन उपकरण, लेकिन यह भी प्रासंगिक ओपन पुस्तकालयों की आवश्यकता होगी (एक डेबियन लिनक्स ओएस पर आप sudo apt-get build-dep r-cran-rgl का उपयोग उन्हें प्राप्त करने के लिए कर सकता है, मुझे लगता है कि ...)

मैं इस प्रयास नहीं किया है। गुड लक ... बारी-बारी से, आप पैकेज मेंटेनर इस एक settable पैरामीटर बनाने के लिए materials3d के माध्यम से या किसी अन्य तरीके से पूछ सकते ...

+0

मैं, स्रोत डाउनलोड करने की कोशिश संपादन रेखा से ऊपर उल्लेख किया * और * 'DESCRIPTION' फ़ाइल (अपने आप को स्थापित करने के लिए देखभाल करने वाले होने के लिए) होगा, और अपलोड यह ftp के माध्यम से 'win-builder.r-project.org' –

2

हालांकि rgl::spheres3d() इस unless you edit and rebuild the rgl source ऐसा नहीं कर सकते, एक वैकल्पिक अपने स्वयं के समारोह लिखना है गोलाकार आकर्षित करने के लिए। यहां एक ऐसा कार्य है जो अक्षांश और देशांतर की समान डिग्री पर स्थित चतुर्भुज के ग्रिड के रूप में एक क्षेत्र प्रदान करता है।

drawSphere = function(xc=0, yc=0, zc=0, r=1, lats=50L, longs=50L, ...) { 
    #xc,yc,zc give centre of sphere, r is radius, lats/longs for resolution 
    vertices = vector(mode = "numeric", length = 12L * lats * longs) 
    vi = 1L 
    for(i in 1:lats) { 
    lat0 = pi * (-0.5 + (i - 1)/lats) 
    z0 = sin(lat0)*r 
    zr0 = cos(lat0)*r 
    lat1 = pi * (-0.5 + i/lats) 
    z1 = sin(lat1)*r 
    zr1 = cos(lat1)*r 
    for(j in 1:longs) { 
     lng1 = 2 * pi * (j - 1)/longs 
     lng2 = 2 * pi * (j)/longs 
     x1 = cos(lng1) 
     y1 = sin(lng1) 
     x2 = cos(lng2) 
     y2 = sin(lng2) 
     vertices[vi] = x1 * zr0 + xc; vi = vi + 1L 
     vertices[vi] = y1 * zr0 + yc; vi = vi + 1L 
     vertices[vi] = z0 + zc;   vi = vi + 1L 
     vertices[vi] = x1 * zr1 + xc; vi = vi + 1L 
     vertices[vi] = y1 * zr1 + yc; vi = vi + 1L 
     vertices[vi] = z1 + zc;   vi = vi + 1L 
     vertices[vi] = x2 * zr1 + xc; vi = vi + 1L 
     vertices[vi] = y2 * zr1 + yc; vi = vi + 1L 
     vertices[vi] = z1 + zc;   vi = vi + 1L 
     vertices[vi] = x2 * zr0 + xc; vi = vi + 1L 
     vertices[vi] = y2 * zr0 + yc; vi = vi + 1L 
     vertices[vi] = z0 + zc;   vi = vi + 1L 
    } 
    } 
    indices = 1:(length(vertices)/3) 
    shade3d(qmesh3d(vertices, indices, homogeneous=F), ...) 
} 

यह इस पर सुधार करने के लिए, icospheres का उपयोग कर उदाहरण के लिए (अर्थात एक विस्तारित icosohedron के रूप में क्षेत्र ड्राइंग) संभव हो जाना चाहिए। लेकिन यदि आप लेट्स बनाते हैं और लंबे समय तक पर्याप्त होते हैं तो यह संस्करण पहले से ही बहुत अच्छे क्षेत्रों को खींचता है।

कार्रवाई में समारोह का एक उदाहरण:

spheres = data.frame(x = c(1,2,3), y = c(1,3,1), z=c(0,0,0), color = c("#992222" , "#222299", "#229922")) 
open3d() 
material3d(ambient = "black", specular = "grey60", emission = "black", shininess = 30.0) 
rgl.clear(type = "lights") 
rgl.light(theta = -30, phi = 60, viewpoint.rel = TRUE, ambient = "#FFFFFF", diffuse = "#FFFFFF", specular = "#FFFFFF", x = NULL, y = NULL, z = NULL) 
rgl.light(theta = -0, phi = 0, viewpoint.rel = TRUE, diffuse = "gray20", specular = "gray25", ambient = "gray80", x = NULL, y = NULL, z = NULL) 
sapply(1:NROW(spheres), function(i) 
    drawSphere(spheres$x[i], spheres$y[i], spheres$z[i], r=1, lats = 400, longs = 400, color=spheres$color[i])) 

enter image description here

+0

हां, अपने स्वयं के क्षेत्र को चित्रित करने का तरीका है। यदि आप केवल एक रंग चाहते हैं तो एक संभावित सुधार यह है कि आप केवल एक क्षेत्र को आकर्षित कर सकते हैं, और इसे 3 डी स्प्राइट के रूप में पुन: उपयोग कर सकते हैं। यह स्मृति को बचाता है, जो शायद आर में कोई फर्क नहीं पड़ता है, लेकिन अगर आप 'rglwidget()' का उपयोग कर दृश्य निर्यात करते हैं तो फ़ाइल आकार में एक उल्लेखनीय अंतर आएगा। – user2554330

2

एक बहुत सरल दृष्टिकोण subdivision3d() उपयोग करने के लिए है। यहां, depth=4 इतना आसान नहीं है, लेकिन आप इसे बढ़ा सकते हैं।

library(rgl) 
sphere <- subdivision3d(cube3d(),depth=4) 
sphere$vb[4,] <- apply(sphere$vb[1:3,], 2, function(x) sqrt(sum(x^2))) 
open3d() 
shade3d(sphere, col="red") 

enter image description here

+2

मानदंड जोड़ना यह और भी बेहतर दिखता है। आप क्षेत्रफल के लिए 'क्षेत्र $ मानदंड <- क्षेत्र $ vb' जोड़कर या अधिक आम तौर पर' आकार <- addNormals (आकार) 'जोड़कर ऐसा कर सकते हैं। – user2554330

+1

मुझे इस दृष्टिकोण की सादगी पसंद है। और इसे 'cube3d() 'के बजाय' dodecahedron3d() 'का उपयोग करके सुधार किया जा सकता है। दुर्भाग्यवश, यह उच्च रिज़ॉल्यूशन क्षेत्रों के लिए काम नहीं करता है। अगर मैं 6 से ऊपर गहराई बढ़ाता हूं तो मुझे स्मृति आवंटन त्रुटियां मिलती हैं। उस ने कहा, गहराई 6 पर dodecahedron3d बहुत पारगम्य दिखता है, अगर – dww

+1

को संसाधित करने में कुछ हद तक धीमा लगता है, तो मेरी पिछली टिप्पणी के आगे, i icosahedron3d() 'गहराई से उपरोक्त 'icosahedron3d()' के सामान्य मानकों को जोड़ने के उपयोगकर्ता उपयोगकर्ता 553030 के सुझाव को जोड़कर, कुछ सुंदर दिखने वाले क्षेत्र – dww

2

यहाँ persp3d.function()

sphere.f <- function(x0 = 0, y0 = 0, z0 = 0, r = 1, n = 101, ...){ 
    f <- function(s, t) cbind(r * cos(s) * cos(t) + x0, 
          r * sin(s) * cos(t) + y0, 
          r * sin(t) + z0) 
    persp3d(f, slim = c(0, pi), tlim = c(0, 2*pi), n = n, add = T, ...) 
} 

sphere.f(col = rainbow) 

enter image description here

+0

यह कुछ बहुत ही चिकनी दिखने वाले क्षेत्रों को बनाता है, और मेरे qmesh3d आधारित फ़ंक्शन की तुलना में प्रक्रिया करने के लिए काफी तेज है। मुझे इस जवाब को स्वीकार करने से पीछे रखने वाली एक बात यह है कि गोलाकारों में ध्रुवों के चारों ओर दोष होते हैं, जहां सतह में अंतराल होते हैं, और भूमध्य रेखा पर थोड़ी सी भीड़ होती है जहां दो गोलार्द्ध काफी मेल नहीं खाते हैं। क्या आपके पास इन मुद्दों को ठीक करने के बारे में कोई विचार है? – dww

+0

@dww; दुर्भाग्य से यह असंभव प्रतीत होता है। दो चर के साथ क्षेत्र व्यक्त करने के लिए कुछ तरीके हैं। लेकिन कम या उच्च घनत्व क्षेत्र और/या डुप्लिकेट अंक किसी भी तरह से उत्पन्न होते हैं। – cuttlefish44

संबंधित मुद्दे