cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can change your system assigned username to something more personal in your community settings. X

Display SVG as 3D Image on Hololens

mziemniewicz
10-Marble

Display SVG as 3D Image on Hololens

Hello, to make a long story short I need multiline preformated text to display on 3D Image like:

$scope.render_html_to_canvas = function(html, can, x, y, width, height) {
     var ctx = can.getContext('2d');
     var xmlsrc='<svg xmlns="http://www.w3.org/2000/svg" width="'+width+'" height="'+height+'">' +
                        '<foreignObject width="100%" height="100%">' +
                        $scope.html_to_xml(html)+
                        '</foreignObject>' +
                        '</svg>';
  
     var data = "data&colon;image/svg+xml;charset=utf-8,"+encodeURIComponent(xmlSrc);
     var img = new Image();
     img.src=data;
     $scope.view.wdg["testImg"].src=img.src;
}

this code works perfect in a preview and mobile, but on hololens it sometimes causes restart of Vuforia Viewer and sometimes nothing....
Can anyone advise me on how to improve it for hololens?

ACCEPTED SOLUTION

Accepted Solutions

Hi @mziemniewicz ,

 

I did have now the same problem and it took for a while until I did manage it to work in preview mode and on HoloLens. May be, it  could be a helpful feedback.

So, following situation:

I wanted to generate a svg format dynamically and used it as source to add there a picture. So the picture should be displayed in the 3dImage widget and also I want to  write some graphics there – for example some markups.

Also adds some multiline text:

 

2019-09-11_18-37-41.gif

 

The widget 3DImage-2 has a value pointing to a particular  svg file but I will replace it by script. The script should generate the graphic and should read also a gif file (here app/resources/Uploaded/2019-01-28_18-34-34.gif) form the upload project folder. Then it will create SVG file format string adding also the gif file as string and will set it to the src property of the 3DImage widget.

The following script:

 

//load the image/picture file from folder as base64
const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }))
///////////////
//Creates a dynamic svg file add to it the "txtL" image base64 string
// and set it to the src property of the imgWidget
$scope.svg_ret = function(txtL,imgWidget) {
      var xmlsrc='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
      xmlsrc=xmlsrc+'<svg xmlns="http://www.w3.org/2000/svg" height="1000" width="600">\n'
      xmlsrc=xmlsrc+'<rect x="50" y="300" width="200" height="100" style="fill:red"/>\n'
      xmlsrc=xmlsrc+'<image  width="700" height="400" href="'+txtL+'"/>'
      xmlsrc=xmlsrc+'<circle cx="350" cy="300" r="40" stroke="black" stroke-width="3" fill="red" margin-top="300px" />\n'
      xmlsrc=xmlsrc+'<text x="10" y="20" style="fill:red;">Several lines:\n'
      xmlsrc=xmlsrc+'<tspan x="10" y="45">First line.</tspan>\n'
      xmlsrc=xmlsrc+'<tspan x="10" y="70">Second line.</tspan>\n'
      xmlsrc=xmlsrc+'</text>\n'
      xmlsrc=xmlsrc+'</svg>'
//some warning to check the string
     console.warn('data&colon;image/svg+xml;base64,'+xmlsrc)
      $scope.view.wdg[imgWidget].src='data&colon;image/svg+xml;base64,'+btoa(xmlsrc);
}

// will start after View enter
$scope.$on('$ionicView.afterEnter', function()  {
 //read 2019-01-28_18-34-34.gif
 toDataURL('app/resources/Uploaded/2019-01-28_18-34-34.gif')
   
  .then(dataUrl => {
    //set the src of 3DImage-2
     $scope.svg_ret(dataUrl,'3DImage-2')
  })
  
}) 

So In preview it looks like:

2019-09-11_18-55-20.gifTested on HoloLens1 and it was also working ok.

View solution in original post

2 REPLIES 2

Hi @mziemniewicz ,

I am not sure what your code does actually in detail and if all these steps are necessary to manage this task. Therefore, may be, here my answer will not be this what you are asking for.

Therefore could your pride the simples demo project where we can see what is the effect of you current code  when it works so the thing about some alternatives

About dynamic source of image I could remember a projected where I had some images in  an repository  and used some REST API call like this one:

//////////////////////////////////////////////////////////////////////
//////////////// get File form Thingworx Repository RESP API
$scope.getFileFromRepository = function(name,image_id) {
 
var req = {
"method":'POST',
"url":'/Thingworx/Things/My_images-File/Services/LoadImage?Appkey="dfab15de-cfbd-4429-98df-7201d728457f" HTTP/1.1',
"Host": 'mrerot7o.studio-trial.thingworx.io:8443',
"Authorization": 'Basic Og==',
"Content-Type": 'application/json',
"Cache-Control": 'no-cache',
"Postman-Token": '5xxxxxxx-9xxx-5xxx-xxxx-d8xxxx1xxxx',
  "headers": {
    "authorization": "Basic Og==",
    "content-type": "application/json",
    "cache-control": "no-cache",
    "postman-token": "cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx6"
  },
  "processData": false,
  "data": "{\"path\":\"/webcam/"+ name +"\"}"
};
$http(req).then(
function(response)   
  {eval(response.data);
    var ret_str='data&colon;image/gif;base64,'+response.data.rows[0].Content;
     $scope.view.wdg[image_id]['imgsrc']=ret_str; 
     }, 
function(response){;}
               );
};
///////////////////////////////////////////////////////////////////////////

Where I call it  from an interval callback

$interval( function(){
 if( global_count_int1 > 7)  global_count_int1=0;
    global_count_int1++;    //this count is contained by the image adress/link
    if(USE_REPOSITORY)
    	{ url_source="pic_0"+global_count_int1+".gif";
          $scope.getFileFromRepository(url_source,'image-2');
    	}
    else
    {  
    if( WEB_SERVER )  
      var url_source="http://localhost:8080/webcam/pic_0"+global_count_int1+".gif";
    else 
      var url_source= "app/resources/Uploaded/pic_0"+global_count_int1+".gif";
     
    $scope.$applyAsync(function() {
      $scope.app.params['image_url']=url_source;
    //this parameter could also be used for direct linking to any image sources
                                  }
                      ); //end applyAsync
    }//finish else USE_REPOSITORY
}
          , 3100);

And this will call the generared url from repository (if USE_REPOSITORY=true)

2019-01-29_10-29-50.gif

So this will change the displayed picture after 3.1 sec

2019-01-29_10-33-15.gif2019-01-29_10-32-59.gif2019-01-29_10-33-28.gif

This code above so far I remember was also working on the HoloLens.

 

When I looked second time on your code - I think you will write some dynamic html and then try to create a picture of it and to set to a image widget. 

May be , it could be a good idea to generate the picture anywhere outside the HoloLens - for example on the Thingworx server and then read it from there....

Hi @mziemniewicz ,

 

I did have now the same problem and it took for a while until I did manage it to work in preview mode and on HoloLens. May be, it  could be a helpful feedback.

So, following situation:

I wanted to generate a svg format dynamically and used it as source to add there a picture. So the picture should be displayed in the 3dImage widget and also I want to  write some graphics there – for example some markups.

Also adds some multiline text:

 

2019-09-11_18-37-41.gif

 

The widget 3DImage-2 has a value pointing to a particular  svg file but I will replace it by script. The script should generate the graphic and should read also a gif file (here app/resources/Uploaded/2019-01-28_18-34-34.gif) form the upload project folder. Then it will create SVG file format string adding also the gif file as string and will set it to the src property of the 3DImage widget.

The following script:

 

//load the image/picture file from folder as base64
const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }))
///////////////
//Creates a dynamic svg file add to it the "txtL" image base64 string
// and set it to the src property of the imgWidget
$scope.svg_ret = function(txtL,imgWidget) {
      var xmlsrc='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
      xmlsrc=xmlsrc+'<svg xmlns="http://www.w3.org/2000/svg" height="1000" width="600">\n'
      xmlsrc=xmlsrc+'<rect x="50" y="300" width="200" height="100" style="fill:red"/>\n'
      xmlsrc=xmlsrc+'<image  width="700" height="400" href="'+txtL+'"/>'
      xmlsrc=xmlsrc+'<circle cx="350" cy="300" r="40" stroke="black" stroke-width="3" fill="red" margin-top="300px" />\n'
      xmlsrc=xmlsrc+'<text x="10" y="20" style="fill:red;">Several lines:\n'
      xmlsrc=xmlsrc+'<tspan x="10" y="45">First line.</tspan>\n'
      xmlsrc=xmlsrc+'<tspan x="10" y="70">Second line.</tspan>\n'
      xmlsrc=xmlsrc+'</text>\n'
      xmlsrc=xmlsrc+'</svg>'
//some warning to check the string
     console.warn('data&colon;image/svg+xml;base64,'+xmlsrc)
      $scope.view.wdg[imgWidget].src='data&colon;image/svg+xml;base64,'+btoa(xmlsrc);
}

// will start after View enter
$scope.$on('$ionicView.afterEnter', function()  {
 //read 2019-01-28_18-34-34.gif
 toDataURL('app/resources/Uploaded/2019-01-28_18-34-34.gif')
   
  .then(dataUrl => {
    //set the src of 3DImage-2
     $scope.svg_ret(dataUrl,'3DImage-2')
  })
  
}) 

So In preview it looks like:

2019-09-11_18-55-20.gifTested on HoloLens1 and it was also working ok.

Announcements

Top Tags