@@ -10,7 +10,7 @@ import { VtkPointPrecision } from 'vtk.js/Sources/Filters/General/Constants';
10
10
11
11
import Constants from './Constants' ;
12
12
13
- const { VtkVaryRadius } = Constants ;
13
+ const { VtkVaryRadius, VtkTCoords } = Constants ;
14
14
const { vtkDebugMacro, vtkErrorMacro, vtkWarningMacro } = macro ;
15
15
16
16
// ----------------------------------------------------------------------------
@@ -52,7 +52,7 @@ function vtkTubeFilter(publicAPI, model) {
52
52
}
53
53
54
54
function generateSlidingNormals ( pts , lines , normals , firstNormal = null ) {
55
- var normal = [ 0.0 , 0.0 , 0 .0] ;
55
+ var normal = [ 0.0 , 0.0 , 1 .0] ;
56
56
const lineData = lines ;
57
57
// lid = 0;
58
58
let npts = lineData [ 0 ] ;
@@ -215,45 +215,54 @@ function vtkTubeFilter(publicAPI, model) {
215
215
sPrev [ i ] = sNext [ i ] ;
216
216
startCapNorm [ i ] = - sPrev [ i ] ;
217
217
}
218
+ console . log ( `First Point: ${ p } ` ) ;
219
+ console . log ( `startCapNorm: ${ startCapNorm } ` ) ;
218
220
vtkMath . normalize ( startCapNorm ) ;
221
+ console . log ( `startCapNorm: ${ startCapNorm } ` ) ;
219
222
} else if ( j === ( npts - 1 ) ) {
220
223
for ( let i = 0 ; i < 3 ; ++ i ) {
221
224
sPrev [ i ] = sNext [ i ] ;
222
225
p [ i ] = pNext [ i ] ;
223
226
endCapNorm [ i ] = sNext [ i ] ;
224
227
}
228
+ console . log ( `Third Point: ${ p } ` ) ;
229
+ console . log ( `endCapNorm: ${ endCapNorm } ` ) ;
225
230
vtkMath . normalize ( endCapNorm ) ;
231
+ console . log ( `endCapNorm: ${ endCapNorm } ` ) ;
226
232
} else {
227
233
for ( let i = 0 ; i < 3 ; ++ i ) {
228
234
p [ i ] = pNext [ i ] ;
229
235
}
236
+ console . log ( `Second Point: ${ p } ` ) ;
230
237
pNext = inPts . slice ( 3 * pts [ j + 1 ] , 3 * ( pts [ j + 1 ] + 1 ) ) ;
231
238
for ( let i = 0 ; i < 3 ; ++ i ) {
232
239
sPrev [ i ] = sNext [ i ] ;
233
240
sNext [ i ] = pNext [ i ] - p [ i ] ;
234
241
}
235
242
}
236
243
237
- if ( vtkMath . norm ( sNext ) === 0.0 ) {
244
+ if ( vtkMath . normalize ( sNext ) === 0.0 ) {
238
245
vtkWarningMacro ( 'Coincident points!' ) ;
239
246
return 0 ;
240
247
}
241
248
242
249
for ( let i = 0 ; i < 3 ; ++ i ) {
243
250
s [ i ] = ( sPrev [ i ] + sNext [ i ] ) / 2.0 ; // average vector
244
251
}
252
+ console . log ( `Average Vector: ${ s } ` ) ;
245
253
246
254
n = inNormals . slice ( 3 * pts [ j ] , 3 * ( pts [ j ] + 1 ) ) ;
255
+ console . log ( `Normal for point ${ pts [ j ] } : ${ n } ` ) ;
247
256
// if s is zero then just use sPrev cross n
248
- if ( vtkMath . norm ( s ) === 0.0 ) {
257
+ if ( vtkMath . normalize ( s ) === 0.0 ) {
249
258
vtkMath . cross ( sPrev , n , s ) ;
250
- if ( vtkMath . norm ( s ) === 0.0 ) {
259
+ if ( vtkMath . normalize ( s ) === 0.0 ) {
251
260
vtkDebugMacro ( 'Using alternate bevel vector' ) ;
252
261
}
253
262
}
254
263
255
264
vtkMath . cross ( s , n , w ) ;
256
- if ( vtkMath . norm ( w ) === 0.0 ) {
265
+ if ( vtkMath . normalize ( w ) === 0.0 ) {
257
266
let msg = 'Bad normal: s = ' ;
258
267
msg += `${ s [ 0 ] } , ${ s [ 1 ] } , ${ s [ 2 ] } ` ;
259
268
msg += ` n = ${ n [ 0 ] } , ${ n [ 1 ] } , ${ n [ 2 ] } ` ;
@@ -284,12 +293,14 @@ function vtkTubeFilter(publicAPI, model) {
284
293
// create points around line
285
294
if ( model . sidesShareVertices ) {
286
295
for ( let k = 0 ; k < model . numberOfSides ; ++ k ) {
296
+ console . log ( `Point ${ ptId } ` ) ;
287
297
for ( let i = 0 ; i < 3 ; ++ i ) {
288
298
normal [ i ] = ( w [ i ] * Math . cos ( k * theta ) ) + ( nP [ i ] * Math . sin ( k * theta ) ) ;
289
299
s [ i ] = p [ i ] + ( model . radius * sFactor * normal [ i ] ) ;
290
300
newPts [ ( 3 * ptId ) + i ] = s [ i ] ;
291
301
newNormals [ ( 3 * ptId ) + i ] = normal [ i ] ;
292
302
}
303
+ console . log ( `${ s } ` ) ;
293
304
outPD . passData ( pd , pts [ j ] , ptId ) ;
294
305
ptId ++ ;
295
306
} // for each side
@@ -319,6 +330,7 @@ function vtkTubeFilter(publicAPI, model) {
319
330
} // else separate vertices
320
331
} // for all points in the polyline
321
332
333
+ console . log ( `NewNormals size: ${ newNormals . length } ` ) ;
322
334
// Produce end points for cap. They are placed at tail end of points.
323
335
if ( model . capping ) {
324
336
let numCapSides = model . numberOfSides ;
@@ -335,9 +347,11 @@ function vtkTubeFilter(publicAPI, model) {
335
347
newPts [ ( 3 * ptId ) + i ] = s [ i ] ;
336
348
newNormals [ ( 3 * ptId ) + i ] = startCapNorm [ i ] ;
337
349
}
350
+ console . log ( `Start cap Id: ${ ptId } : ${ startCapNorm } ` ) ;
338
351
outPD . passData ( pd , pts [ 0 ] , ptId ) ;
339
352
ptId ++ ;
340
353
}
354
+ console . log ( `NewNormals size: ${ newNormals . length } ` ) ;
341
355
342
356
// the end cap
343
357
let endOffset = offset + ( ( npts - 1 ) * model . numberOfSides ) ;
@@ -350,6 +364,7 @@ function vtkTubeFilter(publicAPI, model) {
350
364
newPts [ ( 3 * ptId ) + i ] = s [ i ] ;
351
365
newNormals [ ( 3 * ptId ) + i ] = endCapNorm [ i ] ;
352
366
}
367
+ console . log ( `end cap Id: ${ ptId } : ${ endCapNorm } ` ) ;
353
368
outPD . passData ( pd , pts [ npts - 1 ] , ptId ) ;
354
369
ptId ++ ;
355
370
}
@@ -372,7 +387,7 @@ function vtkTubeFilter(publicAPI, model) {
372
387
for ( let k = offset ; k < ( model . numberOfSides + offset ) ; k += model . onRatio ) {
373
388
i1 = k % model . numberOfSides ;
374
389
i2 = ( k + 1 ) % model . numberOfSides ;
375
- outCellId = newStrips . getNumberOfCells ( ) ;
390
+ outCellId = newStrips . getNumberOfCells ( true ) ;
376
391
newStripsData [ newStripsData . length ] = ( npts * 2 ) ;
377
392
for ( let i = 0 ; i < npts ; ++ i ) {
378
393
i3 = i * model . numberOfSides ;
@@ -385,7 +400,7 @@ function vtkTubeFilter(publicAPI, model) {
385
400
for ( let k = offset ; k < ( model . numberOfSides + offset ) ; k += model . onRatio ) {
386
401
i1 = ( 2 * ( k % model . numberOfSides ) ) + 1 ;
387
402
i2 = 2 * ( ( k + 1 ) % model . numberOfSides ) ;
388
- outCellId = newStrips . getNumberOfCells ( ) ;
403
+ outCellId = newStrips . getNumberOfCells ( true ) ;
389
404
newStripsData [ newStripsData . length ] = ( npts * 2 ) ;
390
405
for ( let i = 0 ; i < npts ; ++ i ) {
391
406
i3 = i * 2 * model . numberOfSides ;
@@ -407,7 +422,7 @@ function vtkTubeFilter(publicAPI, model) {
407
422
}
408
423
409
424
// The start cap
410
- outCellId = newStrips . getNumberOfCells ( ) ;
425
+ outCellId = newStrips . getNumberOfCells ( true ) ;
411
426
newStripsData [ newStripsData . length ] = model . numberOfSides ;
412
427
newStripsData [ newStripsData . length ] = startIdx ;
413
428
newStripsData [ newStripsData . length ] = startIdx + 1 ;
@@ -427,7 +442,7 @@ function vtkTubeFilter(publicAPI, model) {
427
442
428
443
// The end cap - reversed order to be consistent with normal
429
444
startIdx += model . numberOfSides ;
430
- outCellId = newStrips . getNumberOfCells ( ) ;
445
+ outCellId = newStrips . getNumberOfCells ( true ) ;
431
446
newStripsData [ newStripsData . length ] = model . numberOfSides ;
432
447
newStripsData [ newStripsData . length ] = startIdx ;
433
448
newStripsData [ newStripsData . length ] = startIdx + model . numberOfSides - 1 ;
@@ -446,6 +461,93 @@ function vtkTubeFilter(publicAPI, model) {
446
461
}
447
462
}
448
463
464
+ function generateTCoords ( offset , npts , pts , inPts , inScalars , newTCoords ) {
465
+ let numSides = model . numberOfSides ;
466
+ if ( ! model . sidesShareVertices ) {
467
+ numSides = 2 * model . numberOfSides ;
468
+ }
469
+
470
+ let tc = 0.0 ;
471
+ let s0 = 0.0 ;
472
+ let s = 0.0 ;
473
+ const inScalarsData = inScalars . getData ( ) ;
474
+ if ( model . generateTCoords === VtkTCoords . TCOORDS_FROM_SCALARS ) {
475
+ s0 = inScalarsData [ pts [ 0 ] ] ;
476
+ for ( let i = 0 ; i < npts ; ++ i ) {
477
+ s = inScalarsData [ pts [ i ] ] ;
478
+ tc = ( s - s0 ) / model . textureLength ;
479
+ for ( let k = 0 ; k < numSides ; ++ k ) {
480
+ const tcy = k / ( numSides - 1 ) ;
481
+ const tcId = 2 * ( offset + ( i * numSides ) + k ) ;
482
+ newTCoords [ tcId ] = tc ;
483
+ newTCoords [ tcId + 1 ] = tcy ;
484
+ }
485
+ }
486
+ } else if ( model . generateTCoords === VtkTCoords . TCOORDS_FROM_LENGTH ) {
487
+ let len = 0.0 ;
488
+ const xPrev = inPts . slice ( 3 * pts [ 0 ] , 3 * ( pts [ 0 ] + 1 ) ) ;
489
+ for ( let i = 0 ; i < npts ; ++ i ) {
490
+ const x = inPts . slice ( 3 * pts [ i ] , 3 * ( pts [ i ] + 1 ) ) ;
491
+ len += Math . sqrt ( vtkMath . distance2BetweenPoints ( x , xPrev ) ) ;
492
+ tc = len / model . textureLength ;
493
+ for ( let k = 0 ; k < numSides ; ++ k ) {
494
+ const tcy = k / ( numSides - 1 ) ;
495
+ const tcId = 2 * ( offset + ( i * numSides ) + k ) ;
496
+ newTCoords [ tcId ] = tc ;
497
+ newTCoords [ tcId + 1 ] = tcy ;
498
+ }
499
+ for ( let k = 0 ; k < 3 ; ++ k ) {
500
+ xPrev [ k ] = x [ k ] ;
501
+ }
502
+ }
503
+ } else if ( model . generateTCoords === VtkTCoords . TCOORDS_FROM_NORMALIZED_LENGTH ) {
504
+ let len = 0.0 ;
505
+ let len1 = 0.0 ;
506
+ let xPrev = inPts . slice ( 3 * pts [ 0 ] , 3 * ( pts [ 0 ] + 1 ) ) ;
507
+ for ( let i = 0 ; i < npts ; ++ i ) {
508
+ const x = inPts . slice ( 3 * pts [ i ] , 3 * ( pts [ i ] + 1 ) ) ;
509
+ len1 += Math . sqrt ( vtkMath . distance2BetweenPoints ( x , xPrev ) ) ;
510
+ for ( let k = 0 ; k < 3 ; ++ k ) {
511
+ xPrev [ k ] = x [ k ] ;
512
+ }
513
+ }
514
+ xPrev = inPts . slice ( 3 * pts [ 0 ] , 3 * ( pts [ 0 ] + 1 ) ) ;
515
+ for ( let i = 0 ; i < npts ; ++ i ) {
516
+ const x = inPts . slice ( 3 * pts [ i ] , 3 * ( pts [ i ] + 1 ) ) ;
517
+ len += Math . sqrt ( vtkMath . distance2BetweenPoints ( x , xPrev ) ) ;
518
+ tc = len / len1 ;
519
+ for ( let k = 0 ; k < numSides ; ++ k ) {
520
+ const tcy = k / ( numSides - 1 ) ;
521
+ const tcId = 2 * ( offset + ( i * numSides ) + k ) ;
522
+ newTCoords [ tcId ] = tc ;
523
+ newTCoords [ tcId + 1 ] = tcy ;
524
+ }
525
+ for ( let k = 0 ; k < 3 ; ++ k ) {
526
+ xPrev [ k ] = x [ k ] ;
527
+ }
528
+ }
529
+ }
530
+
531
+ // Capping, set the endpoints as appropriate
532
+ if ( model . capping ) {
533
+ const startIdx = offset + ( npts * numSides ) ;
534
+
535
+ // start cap
536
+ for ( let ik = 0 ; ik < model . numberOfSides ; ++ ik ) {
537
+ const tcId = 2 * ( startIdx + ik ) ;
538
+ newTCoords [ tcId ] = 0.0 ;
539
+ newTCoords [ tcId + 1 ] = 0.0 ;
540
+ }
541
+
542
+ // end cap
543
+ for ( let ik = 0 ; ik < model . numberOfSides ; ++ ik ) {
544
+ const tcId = 2 * ( startIdx + model . numberOfSides + ik ) ;
545
+ newTCoords [ tcId ] = 0.0 ;
546
+ newTCoords [ tcId + 1 ] = 0.0 ;
547
+ }
548
+ }
549
+ }
550
+
449
551
publicAPI . requestData = ( inData , outData ) => { // implement requestData
450
552
// pass through for now
451
553
outData [ 0 ] = inData [ 0 ] ;
@@ -486,7 +588,11 @@ function vtkTubeFilter(publicAPI, model) {
486
588
const newPts = vtkPoints . newInstance (
487
589
{ dataType : pointType , size : ( numNewPts * 3 ) , numberOfComponents : 3 } ) ;
488
590
// const newPtsData = newPts.getData();
489
- const newNormalsData = new Float32Array ( 3 * numNewPts ) ;
591
+ let numNormals = 3 * numNewPts ;
592
+ if ( model . capping ) {
593
+ numNormals = 3 * ( numNewPts + ( 2 * model . numberOfSides ) ) ;
594
+ }
595
+ const newNormalsData = new Float32Array ( numNormals ) ;
490
596
const newNormals = vtkDataArray . newInstance (
491
597
{ numberOfComponents : 3 , values : newNormalsData , name : 'TubeNormals' } ) ;
492
598
const newStripsData = new Uint32Array ( 0 ) ;
@@ -534,7 +640,18 @@ function vtkTubeFilter(publicAPI, model) {
534
640
535
641
const outPD = output . getPointData ( ) ;
536
642
outPD . copyNormalsOff ( ) ;
643
+
537
644
// TCoords
645
+ let newTCoords = null ;
646
+ if ( ( model . generateTCoords === VtkTCoords . TCOORDS_FROM_SCALARS && inScalars ) ||
647
+ model . generateTCoords === VtkTCoords . TCOORDS_FROM_LENGTH ||
648
+ model . generateTCoords === VtkTCoords . TCOORDS_FROM_NORMALIZED_LENGTH ) {
649
+ const newTCoordsData = new Float32Array ( 2 * numNewPts ) ;
650
+ newTCoords = vtkDataArray . newInstance (
651
+ { numberOfComponents : 2 , values : newTCoordsData , name : 'TCoords' } ) ;
652
+ outPD . copyTCoordsOff ( ) ;
653
+ }
654
+
538
655
outPD . passData ( input . getPointData ( ) ) ;
539
656
540
657
// Create points along each polyline that are connected into numberOfSides
@@ -562,6 +679,9 @@ function vtkTubeFilter(publicAPI, model) {
562
679
// generate strips for the polyline
563
680
generateStrips ( offset , npts , inCellId , input . getCellData ( ) , outCD , newStrips ) ;
564
681
// generate texture coordinates for the polyline
682
+ if ( newTCoords ) {
683
+ generateTCoords ( offset , npts , pts , inPts . getData ( ) , inScalars , newTCoords . getData ( ) ) ;
684
+ }
565
685
} else {
566
686
// skip tubing this line
567
687
vtkWarningMacro ( 'Could not generate points' ) ;
@@ -574,7 +694,10 @@ function vtkTubeFilter(publicAPI, model) {
574
694
575
695
output . setPoints ( newPts ) ;
576
696
output . setStrips ( newStrips ) ;
697
+ output . setPointData ( outPD ) ;
577
698
outPD . setNormals ( newNormals ) ;
699
+ const s = JSON . stringify ( output . getState ( ) ) ;
700
+ console . log ( `${ s } ` ) ;
578
701
outData [ 0 ] = output ;
579
702
} ;
580
703
}
@@ -595,6 +718,8 @@ const DEFAULT_VALUES = {
595
718
capping : false ,
596
719
onRatio : 1 ,
597
720
offset : 0 ,
721
+ generateTCoords : VtkTCoords . TCOORDS_OFF ,
722
+ textureLength : 1.0 ,
598
723
} ;
599
724
600
725
// ----------------------------------------------------------------------------
@@ -616,6 +741,8 @@ export function extend(publicAPI, model, initialValues = {}) {
616
741
'capping' ,
617
742
'onRatio' ,
618
743
'offset' ,
744
+ 'generateTCoords' ,
745
+ 'textureLength' ,
619
746
] ) ;
620
747
621
748
// Make this a VTK object
0 commit comments