comparison Sources/OrthancExplorer.js @ 31:ab231760799d

added button to import STL
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 04 Apr 2024 18:05:13 +0200
parents dd0cd39e6259
children 13698d34e059
comparison
equal deleted inserted replaced
30:3570c23764d4 31:ab231760799d
145 }); 145 });
146 } 146 }
147 } 147 }
148 148
149 149
150 $('#series').live('pagebeforeshow', function() { 150 function AddGenerateFromNIfTIButton(studyId) {
151 var seriesId = $.mobile.pageData.uuid; 151 if (${HAS_CREATE_DICOM_STL} &&
152 152 ${SHOW_NIFTI_BUTTON}) {
153 $('#stl-viewer-series').remove(); 153 $('#stl-attach-nifti').remove();
154 $('#stl-generate-rtstruct-series').remove(); 154
155 155 var nifti = $('<a>')
156 GetResource('/series/' + seriesId, function(series) { 156 .attr('id', 'stl-attach-nifti')
157 if (series['Instances'].length == 1) {
158 var instanceId = series['Instances'][0];
159
160 $.ajax({
161 url: '/instances/' + instanceId + '/metadata/SopClassUid',
162 success: function(sopClassUid) {
163
164 if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_STL) {
165 // This is an "Encapsulated STL Storage" IOD, register the button
166 AddOpenStlViewerButton(instanceId, 'stl-viewer-series', 'series-info');
167 }
168 else if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_RT_STRUCT) {
169 AddGenerateFromRtStructButton(instanceId, 'stl-generate-rtstruct-series', 'series-info');
170 }
171
172 }
173 });
174 }
175 });
176 });
177
178
179 $('#instance').live('pagebeforeshow', function() {
180 var instanceId = $.mobile.pageData.uuid;
181
182 $('#stl-viewer-instance').remove();
183 $('#stl-generate-rtstruct-instance').remove();
184
185 $.ajax({
186 url: '/instances/' + instanceId + '/metadata/SopClassUid',
187 success: function(sopClassUid) {
188
189 if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_STL) {
190 // This is an "Encapsulated STL Storage" IOD, register the button
191 AddOpenStlViewerButton(instanceId, 'stl-viewer-instance', 'instance-info');
192 }
193 else if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_RT_STRUCT) {
194 AddGenerateFromRtStructButton(instanceId, 'stl-generate-rtstruct-instance', 'instance-info');
195 }
196
197 }
198 });
199 });
200
201
202 $('#study').live('pagebeforeshow', function() {
203 if (${HAS_CREATE_DICOM_STL}) {
204 var studyId = $.mobile.pageData.uuid;
205
206 $('#stl-attach-nifti-study').remove();
207
208 var b = $('<a>')
209 .attr('id', 'stl-attach-nifti-study')
210 .attr('data-role', 'button') 157 .attr('data-role', 'button')
211 .attr('href', '#') 158 .attr('href', '#')
212 .attr('data-icon', 'search') 159 .attr('data-icon', 'search')
213 .attr('data-theme', 'e') 160 .attr('data-theme', 'e')
214 .text('Attach NIfTI 3D model') 161 .text('Attach NIfTI 3D model')
215 .button(); 162 .button();
216 163
217 b.insertAfter($('#study-info')); 164 nifti.insertAfter($('#study-info'));
218 b.click(function() { 165 nifti.click(function() {
219 166
220 var options = $('<ul>') 167 var options = $('<ul>')
221 .attr('data-divider-theme', 'd') 168 .attr('data-divider-theme', 'd')
222 .attr('data-role', 'listview'); 169 .attr('data-role', 'listview');
223 170
224 var upload = $('<input>') 171 var upload = $('<input>')
225 .attr('type', 'file') 172 .attr('type', 'file')
226 .attr('id', 'stl-attach-nifti-study-upload') 173 .attr('id', 'stl-attach-nifti-upload')
227 .attr('data-theme', 'a'); 174 .attr('data-theme', 'a');
228 175
229 options.append($('<li>').text('Choose the NIfTI file:')); 176 options.append($('<li>').text('Choose the NIfTI file:'));
230 options.append($('<li>').append(upload)); 177 options.append($('<li>').append(upload));
231 options.append($('<li>').text('Resolution:')); 178 options.append($('<li>').text('Resolution:'));
232 options.append($('<li>').append($('<select>') 179 options.append($('<li>').append($('<select>')
233 .attr('id', 'stl-attach-nifti-study-resolution') 180 .attr('id', 'stl-attach-nifti-resolution')
234 .attr('data-theme', 'a') 181 .attr('data-theme', 'a')
235 .append($('<option>').attr('value', '256').text('256')) 182 .append($('<option>').attr('value', '256').text('256'))
236 .append($('<option>').attr('value', '128').text('128')) 183 .append($('<option>').attr('value', '128').text('128'))
237 .append($('<option>').attr('value', '512').text('512')))); 184 .append($('<option>').attr('value', '512').text('512'))));
238 options.append($('<li>') 185 options.append($('<li>')
239 .append($('<input>') 186 .append($('<input>')
240 .attr('id', 'stl-attach-nifti-study-smooth') 187 .attr('id', 'stl-attach-nifti-smooth')
241 .attr('type', 'checkbox') 188 .attr('type', 'checkbox')
242 .attr('data-theme', 'a') 189 .attr('data-theme', 'a')
243 .attr('checked', '')) 190 .attr('checked', ''))
244 .append($('<label>') 191 .append($('<label>')
245 .attr('for', 'stl-attach-nifti-study-smooth') 192 .attr('for', 'stl-attach-nifti-smooth')
246 .text('Smooth volume'))); 193 .text('Smooth volume')));
247 194
248 options.append($('<li>').append( 195 options.append($('<li>').append(
249 $('<a>') 196 $('<a>')
250 .attr('href', '#') 197 .attr('href', '#')
251 .attr('rel', 'close').attr('data-theme', 'b') 198 .attr('rel', 'close').attr('data-theme', 'b')
252 .text('Generate') 199 .text('Generate')
253 .click(function(e) { 200 .click(function(e) {
254 e.preventDefault(); 201 e.preventDefault();
255 202
256 var fileInput = document.getElementById('stl-attach-nifti-study-upload'); 203 var fileInput = document.getElementById('stl-attach-nifti-upload');
257 var resolution = $('#stl-attach-nifti-study-resolution').val(); 204 var resolution = $('#stl-attach-nifti-resolution').val();
258 var smooth = $('#stl-attach-nifti-study-smooth').is(':checked'); 205 var smooth = $('#stl-attach-nifti-smooth').is(':checked');
259 206
260 if (fileInput.files.length == 0) { 207 if (fileInput.files.length == 0) {
261 alert('No NIfTI file was selected'); 208 alert('No NIfTI file was selected');
262 return; 209 return;
263 } 210 }
302 headerClose: true, 249 headerClose: true,
303 forceInput: false, 250 forceInput: false,
304 width: '100%', 251 width: '100%',
305 blankContent: options 252 blankContent: options
306 }); 253 });
307
308 }); 254 });
309 } 255 }
256 }
257
258
259 function AddImportSTLButton(studyId) {
260 if (${HAS_CREATE_DICOM_STL}) {
261 $('#stl-attach-instance').remove();
262
263 var instance = $('<a>')
264 .attr('id', 'stl-attach-instance')
265 .attr('data-role', 'button')
266 .attr('href', '#')
267 .attr('data-icon', 'search')
268 .attr('data-theme', 'e')
269 .text('Attach STL model')
270 .button();
271
272 instance.insertAfter($('#study-info'));
273 instance.click(function() {
274
275 var options = $('<ul>')
276 .attr('data-divider-theme', 'd')
277 .attr('data-role', 'listview');
278
279 var upload = $('<input>')
280 .attr('type', 'file')
281 .attr('id', 'stl-attach-instance-upload')
282 .attr('data-theme', 'a');
283
284 options.append($('<li>').text('Choose the STL file:'));
285 options.append($('<li>').append(upload));
286
287 options.append($('<li>').text('Series description:'));
288 options.append($('<li>').append($('<input>')
289 .attr('type', 'text')
290 .attr('id', 'stl-attach-instance-description')
291 .attr('data-theme', 'b')
292 .val('Imported STL')));
293
294 options.append($('<li>').append(
295 $('<a>')
296 .attr('href', '#')
297 .attr('rel', 'close').attr('data-theme', 'b')
298 .text('Import')
299 .click(function(e) {
300 e.preventDefault();
301
302 var fileInput = document.getElementById('stl-attach-instance-upload');
303 var description = $('#stl-attach-instance-description').val();
304
305 if (fileInput.files.length == 0) {
306 alert('No Instance file was selected');
307 return;
308 }
309
310 reader = new FileReader();
311 reader.onload = function() {
312
313 // https://github.com/axios/axios/issues/513
314 var stl = reader.result;
315 var stlBase64 = btoa(new Uint8Array(stl).reduce((data, byte) => data + String.fromCharCode(byte), ''));
316
317 $.ajax({
318 url: '../tools/create-dicom',
319 type: 'POST',
320 data: JSON.stringify({
321 'Content' : 'data:model/stl;base64,' + stlBase64,
322 'Parent' : studyId,
323 'Tags' : {
324 'SeriesDescription' : description
325 }
326 }),
327 dataType: 'json',
328 success: function(s) {
329 $.mobile.changePage('#series?uuid=' + s.ParentSeries, {
330 allowSamePageTransition: true
331 });
332 },
333 error: function() {
334 alert('Error while generating the 3D model');
335 }
336 });
337
338 };
339
340 reader.readAsArrayBuffer(fileInput.files[0]);
341 })));
342
343 // Launch the dialog
344 $('#dialog').simpledialog2({
345 mode: 'blank',
346 animate: false,
347 headerText: 'Attach STL',
348 headerClose: true,
349 forceInput: false,
350 width: '100%',
351 blankContent: options
352 });
353 });
354 }
355 }
356
357
358
359 $('#series').live('pagebeforeshow', function() {
360 var seriesId = $.mobile.pageData.uuid;
361
362 $('#stl-viewer-series').remove();
363 $('#stl-generate-rtstruct-series').remove();
364
365 GetResource('/series/' + seriesId, function(series) {
366 if (series['Instances'].length == 1) {
367 var instanceId = series['Instances'][0];
368
369 $.ajax({
370 url: '/instances/' + instanceId + '/metadata/SopClassUid',
371 success: function(sopClassUid) {
372
373 if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_STL) {
374 // This is an "Encapsulated STL Storage" IOD, register the button
375 AddOpenStlViewerButton(instanceId, 'stl-viewer-series', 'series-info');
376 }
377 else if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_RT_STRUCT) {
378 AddGenerateFromRtStructButton(instanceId, 'stl-generate-rtstruct-series', 'series-info');
379 }
380
381 }
382 });
383 }
384 });
310 }); 385 });
386
387
388 $('#instance').live('pagebeforeshow', function() {
389 var instanceId = $.mobile.pageData.uuid;
390
391 $('#stl-viewer-instance').remove();
392 $('#stl-generate-rtstruct-instance').remove();
393
394 $.ajax({
395 url: '/instances/' + instanceId + '/metadata/SopClassUid',
396 success: function(sopClassUid) {
397
398 if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_STL) {
399 // This is an "Encapsulated STL Storage" IOD, register the button
400 AddOpenStlViewerButton(instanceId, 'stl-viewer-instance', 'instance-info');
401 }
402 else if (sopClassUid == STL_PLUGIN_SOP_CLASS_UID_RT_STRUCT) {
403 AddGenerateFromRtStructButton(instanceId, 'stl-generate-rtstruct-instance', 'instance-info');
404 }
405
406 }
407 });
408 });
409
410
411 $('#study').live('pagebeforeshow', function() {
412 var studyId = $.mobile.pageData.uuid;
413 AddImportSTLButton(studyId);
414 AddGenerateFromNIfTIButton(studyId);
415 });