चमकदार ऐप rglwidget एक ही रोटेशन के साथ एक और प्लॉट उत्पन्न करने के लिए उपयोगकर्ता मैट्रिक्स प्राप्त करें



shiny (1)

कारण rgl:par3d() कुछ भी वापस नहीं करता है क्योंकि rgl पैकेज वास्तव में चमकदार के लिए दृश्य का प्रबंध नहीं कर रहा है। जावास्क्रिप्ट आधारित rglwidget लाइब्रेरी जो कि rglwidget का लाभ उठाती WebGL , और आप इस दृश्य को एक और बहुत ही संगत जीएल लाइब्रेरी में कॉपी कर रहे हैं (हो सकता है कि वे एक ही संकलित लाइब्रेरी का उपयोग करें, लेकिन मुझे इसमें शक है) और चमकदार में प्रदर्शित तो rgl.dev() आपकी मदद नहीं करेगा।

AFAIK, इन मूल्यों को प्राप्त करना आसान नहीं है क्योंकि वे rglwidget javascript में rglwidget , लेकिन मैं उन्हें प्राप्त करना चाहता था, इसलिए मैंने एक चमकदार कस्टम इनपुट नियंत्रण बनाया जो यह कर सकता है यह काम का एक उचित हिस्सा था, और एक आसान तरीका हो सकता है, लेकिन मैंने इसे नहीं देखा और कम से कम मुझे पता है कि अब चमकदार के लिए कस्टम इनपुट नियंत्रण कैसे बनाएं। अगर कोई एक आसान तरीका जानता है, तो कृपया मुझे उजागर करें

यहां जावास्क्रिप्ट है, यह एक www सबफ़ोल्डर में जाता है जिसे आप एक ही निर्देशिका में अपने चमकदार कोड के रूप में सहेजते हैं।

rglwidgetaux.js

// rglwidgetaux control for querying shiny rglwiget

var rglwidgetauxBinding = new Shiny.InputBinding();
$.extend(rglwidgetauxBinding, {
  find: function(scope) {
    return $(scope).find(".rglWidgetAux");
  },
  getValue: function(el) {
    return el.value;
  },
  setValue: function(el, value) {
  //  $(el).text(value);
     el.value = value;
  },
  getState: function(el) {
    return { value: this.getValue(el) };
  },
   receiveMessage: function(el, data) {
    var $el = $(el);

    switch (data.cmd) {
       case "test":alert("Recieved Message");
                    break;
       case "getpar3d":
                    var rglel = $("#"+data.rglwidgetId);
                    if (rglel.length===0){
                       alert("bad rglwidgetId:"+ data.rglwidgetId);
                       return null;
                    }
                    var rglinst = rglel[0].rglinstance;
                    var sid = rglinst.scene.rootSubscene;
                    var par3d = rglinst.getObj(sid).par3d;
                    this.setValue(el,JSON.stringify(par3d));
                    $el.trigger("change"); // tell myself that I have changed
                    break;
    }
  },  
  subscribe: function(el, callback) {
    $(el).on("change.rglwidgetauxBinding", function(e) {
      callback();
    });
  },
  unsubscribe: function(el) {
    $(el).off(".rglwidgetauxBinding");
  }
});
Shiny.inputBindings.register(rglwidgetauxBinding);

यहां आर / चमकदार कोड है यह सामान्य परीक्षण दृश्य का उपयोग करता है और उसके पास पर्दे userMatrix लिए एक बटन userMatrix और उसे एक तालिका में दिखाया जाता है। मैंने userMatrix इस्तेमाल किया और न कि modelMatrix क्योंकि पूर्व माउस के साथ बदलना आसान है, इसलिए आप देख सकते हैं कि आपको सबसे ताज़ा मूल्य मिले हैं।

ध्यान दें कि नाम "ऐप। आर" वास्तव में वैकल्पिक नहीं है या तो आपको इसका उपयोग करना होगा, या फ़ाइल को "ui.r" और "server.r" में विभाजित करना होगा, अन्यथा यह ऊपर की जावास्क्रिप्ट फाइल को आयात नहीं करेगा

app.R

library(shiny)
library(rgl)
library(htmlwidgets)
library(jsonlite)

rglwgtctrl <- function(inputId, value="", nrows, ncols) {
  # This code includes the javascript that we need and defines the html
  tagList(
    singleton(tags$head(tags$script(src = "rglwidgetaux.js"))),
    tags$div(id = inputId,class = "rglWidgetAux",as.character(value))
  )
}

ui <- fluidPage(
    rglwgtctrl('ctrlplot3d'),
    actionButton("regen", "Regen Scene"),
    actionButton("queryumat", "Query User Matrix"),
    rglwidgetOutput("plot3d"),
    tableOutput("usermatrix")
)

server <- function(input, output, session) 
{
  observe({
    # tell our rglWidgetAux to query the plot3d for its par3d
    input$queryumat
    session$sendInputMessage("ctrlplot3d",list("cmd"="getpar3d","rglwidgetId"="plot3d"))
  })

  output$usermatrix <- renderTable({
    # grab the user matrix from the par3d stored in our rglWidgetAux
    # note we are using two different "validate"s here, which is quite the pain if you 
    # don't notice that it is declared in two different libraries
    shiny::validate(need(!is.null(input$ctrlplot3d),"User Matrix not yet queried"))
    umat <- matrix(0,4,4)
    jsonpar3d <- input$ctrlplot3d
    if (jsonlite::validate(jsonpar3d)){
      par3dout <- fromJSON(jsonpar3d)
      umat <- matrix(unlist(par3dout$userMatrix),4,4) # make list into matrix
    }
    return(umat)
  })

  scenegen <- reactive({
     # make a random scene
     input$regen
     n <- 1000
     x <- sort(rnorm(n))
     y <- rnorm(n)
     z <- rnorm(n) + atan2(x, y)
     plot3d(x, y, z, col = rainbow(n))
     scene1 <- scene3d()
     rgl.close() # make the app window go away
     return(scene1)
  })
  output$plot3d <- renderRglwidget({ rglwidget(scenegen()) })
}

shinyApp(ui=ui, server=server)

और अंत में यह ऐसा दिखता है:

ध्यान दें कि मैं इसे सेट करता हूं ताकि आप उसे कमांड जोड़ सकें, आप (शायद) पैरामीटर्स बदल सकते हैं और इस पर आधारित नियंत्रण के साथ कुछ और

यह भी ध्यान रखें कि यहां par3d संरचना (json में बदल जाती है और फिर rglwidget जावास्क्रिप्ट से आर) और rgl में से एक बिल्कुल समान नहीं है, उदाहरण के लिए मुझे userMatrix को userMatrix करना पड़ा क्योंकि WebGL इसे नाम सूची के रूप में पसंद करता है अपेक्षित के रूप में आने वाले अन्य मैट्रिक्स के विपरीत

मेरे पास एक चमकदार ऐप है और इसमें एक आरजीएल 3 डी प्लॉट को एकीकृत किया गया है। मैं rglwidget पैकेज से renderRglwidget का उपयोग कर रहा हूँ मेरे चमकदार एप में webgl का उपयोग कर rgl ग्राफिक्स को सम्मिलित करने के लिए।

ऐप में उपयोगकर्ता ग्राफ़िक को घुमा सकता है अब मैं रोटेशन स्टेट को सहेजना चाहता हूं, इसलिए उपयोगकर्ता मैट्रिक्स या मॉडल मैट्रिक्स बाद में उसी रोटेशन के साथ एक ऐसी साजिश उत्पन्न करता है, क्योंकि उपयोगकर्ता ने पिछले ग्राफ़ को छोड़ दिया था।

यहां मैं उपयोगकर्ता मैट्रिक्स और अन्य मापदंडों को संचित करने वाले जावा चर के बारे में कुछ पढ़ता हूं। क्या मैं उन्हें अपने चमकदार ऐप (आर कोड) के भीतर से एक्सेस कर सकता हूं?

खुद आरजीएल में मैं rotationMatrix <- rgl.projection()$model या rotationMatrix <- par3d()$modelMatrix rotationMatrix <- rgl.projection()$model rotationMatrix <- par3d()$modelMatrix स्टोर करने के लिए उपयोग कर सकते हैं। लेकिन जब से मेरे मामले में ग्राफिक आरजीएल में घुमाया नहीं है, ये फ़ंक्शन मुझे मदद नहीं करते हैं।

मैंने जो कोशिश की वह है:

library(shiny)
library(rgl)
library(rglwidget)

ui <- fluidPage(
  rglwidgetOutput("3D-plot"),
  actionButton("showMatrix", "show rotation Matrix")
)

server <- function(input, output, session){
  open3d(useNULL = T)
  x <- sort(rnorm(1000))
  y <- rnorm(1000)
  z <- rnorm(1000) + atan2(x, y)
  plot3d(x, y, z, col = rainbow(1000))
  scene1 <- scene3d()
  rgl.close()

  output$"3D-plot" <- renderRglwidget({
    rglwidget(scene1)
  })
  observe({
    input$showMatrix
    par3d()$modelMatrix
  })
}


shinyApp(ui=ui, server=server)

लेकिन par3d()$modelMatrix को कुछ भी वापस नहीं लगता।