-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathoccupancy_dual_contouring.py
1097 lines (976 loc) · 49.8 KB
/
occupancy_dual_contouring.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# This code is written by Jisung Hwang (4011hjs@kaist.ac.kr) in 2024.
# This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
pfvtab = [
[],
[[13, 2, 17, 3, 15, 1, 13]],
[[19, 4, 13, 1, 15, 5, 19]],
[[13, 2, 17, 3, 15, 5, 19, 4, 13]],
[[13, 6, 21, 7, 17, 2, 13]],
[[15, 1, 13, 6, 21, 7, 17, 3, 15]],
[[19, 4, 13, 1, 15, 5, 19], [14, 6, 21, 7, 17, 2, 14]],
[[21, 7, 17, 3, 15, 5, 19, 4, 13, 6, 21]],
[[21, 6, 13, 4, 19, 10, 21]],
[[13, 2, 17, 3, 15, 1, 13], [21, 6, 14, 4, 19, 10, 21]],
[[13, 1, 15, 5, 19, 10, 21, 6, 13]],
[[19, 10, 21, 6, 13, 2, 17, 3, 15, 5, 19]],
[[17, 2, 13, 4, 19, 10, 21, 7, 17]],
[[19, 10, 21, 7, 17, 3, 15, 1, 13, 4, 19]],
[[21, 7, 17, 2, 13, 1, 15, 5, 19, 10, 21]],
[[21, 7, 17, 3, 15, 5, 19, 10, 21]],
[[23, 8, 15, 3, 17, 9, 23]],
[[15, 1, 13, 2, 17, 9, 23, 8, 15]],
[[15, 5, 19, 4, 13, 1, 15], [23, 8, 16, 3, 17, 9, 23]],
[[17, 9, 23, 8, 15, 5, 19, 4, 13, 2, 17]],
[[21, 7, 17, 2, 13, 6, 21], [18, 9, 23, 8, 15, 3, 18]],
[[23, 8, 15, 1, 13, 6, 21, 7, 17, 9, 23]],
[[19, 4, 13, 1, 15, 5, 19], [14, 6, 21, 7, 17, 2, 14], [23, 8, 16, 3, 18, 9, 23]],
[[21, 7, 17, 9, 23, 8, 15, 5, 19, 4, 13, 6, 21]],
[[23, 8, 15, 3, 17, 9, 23], [21, 6, 13, 4, 19, 10, 21]],
[[15, 1, 13, 2, 17, 9, 23, 8, 15], [21, 6, 14, 4, 19, 10, 21]],
[[13, 1, 15, 5, 19, 10, 21, 6, 13], [23, 8, 16, 3, 17, 9, 23]],
[[17, 9, 23, 8, 15, 5, 19, 10, 21, 6, 13, 2, 17]],
[[17, 2, 13, 4, 19, 10, 21, 7, 17], [18, 9, 23, 8, 15, 3, 18]],
[[23, 8, 15, 1, 13, 4, 19, 10, 21, 7, 17, 9, 23]],
[[21, 7, 17, 2, 13, 1, 15, 5, 19, 10, 21], [23, 8, 16, 3, 18, 9, 23]],
[[21, 7, 17, 9, 23, 8, 15, 5, 19, 10, 21]],
[[15, 8, 23, 11, 19, 5, 15]],
[[17, 3, 15, 1, 13, 2, 17], [16, 8, 23, 11, 19, 5, 16]],
[[13, 1, 15, 8, 23, 11, 19, 4, 13]],
[[23, 11, 19, 4, 13, 2, 17, 3, 15, 8, 23]],
[[13, 6, 21, 7, 17, 2, 13], [15, 8, 23, 11, 19, 5, 15]],
[[15, 1, 13, 6, 21, 7, 17, 3, 15], [16, 8, 23, 11, 19, 5, 16]],
[[13, 1, 15, 8, 23, 11, 19, 4, 13], [14, 6, 21, 7, 17, 2, 14]],
[[21, 7, 17, 3, 15, 8, 23, 11, 19, 4, 13, 6, 21]],
[[19, 10, 21, 6, 13, 4, 19], [23, 11, 20, 5, 15, 8, 23]],
[[13, 2, 17, 3, 15, 1, 13], [21, 6, 14, 4, 19, 10, 21], [16, 8, 23, 11, 20, 5, 16]],
[[15, 8, 23, 11, 19, 10, 21, 6, 13, 1, 15]],
[[19, 10, 21, 6, 13, 2, 17, 3, 15, 8, 23, 11, 19]],
[[13, 4, 19, 10, 21, 7, 17, 2, 13], [23, 11, 20, 5, 15, 8, 23]],
[[19, 10, 21, 7, 17, 3, 15, 1, 13, 4, 19], [16, 8, 23, 11, 20, 5, 16]],
[[21, 7, 17, 2, 13, 1, 15, 8, 23, 11, 19, 10, 21]],
[[19, 10, 21, 7, 17, 3, 15, 8, 23, 11, 19]],
[[15, 3, 17, 9, 23, 11, 19, 5, 15]],
[[23, 11, 19, 5, 15, 1, 13, 2, 17, 9, 23]],
[[17, 9, 23, 11, 19, 4, 13, 1, 15, 3, 17]],
[[17, 9, 23, 11, 19, 4, 13, 2, 17]],
[[15, 3, 18, 9, 23, 11, 19, 5, 15], [21, 7, 17, 2, 13, 6, 21]],
[[13, 6, 21, 7, 17, 9, 23, 11, 19, 5, 15, 1, 13]],
[[18, 9, 23, 11, 19, 4, 13, 1, 15, 3, 18], [14, 6, 21, 7, 17, 2, 14]],
[[17, 9, 23, 11, 19, 4, 13, 6, 21, 7, 17]],
[[20, 5, 15, 3, 17, 9, 23, 11, 20], [19, 10, 21, 6, 13, 4, 19]],
[[23, 11, 20, 5, 15, 1, 13, 2, 17, 9, 23], [21, 6, 14, 4, 19, 10, 21]],
[[17, 9, 23, 11, 19, 10, 21, 6, 13, 1, 15, 3, 17]],
[[23, 11, 19, 10, 21, 6, 13, 2, 17, 9, 23]],
[[17, 2, 13, 4, 19, 10, 21, 7, 17], [15, 3, 18, 9, 23, 11, 20, 5, 15]],
[[19, 10, 21, 7, 17, 9, 23, 11, 20, 5, 15, 1, 13, 4, 19]],
[[21, 7, 17, 2, 13, 1, 15, 3, 18, 9, 23, 11, 19, 10, 21]],
[[17, 9, 23, 11, 19, 10, 21, 7, 17]],
[[23, 9, 17, 7, 21, 12, 23]],
[[17, 3, 15, 1, 13, 2, 17], [23, 9, 18, 7, 21, 12, 23]],
[[19, 4, 13, 1, 15, 5, 19], [23, 9, 17, 7, 21, 12, 23]],
[[13, 2, 17, 3, 15, 5, 19, 4, 13], [23, 9, 18, 7, 21, 12, 23]],
[[17, 2, 13, 6, 21, 12, 23, 9, 17]],
[[21, 12, 23, 9, 17, 3, 15, 1, 13, 6, 21]],
[[17, 2, 14, 6, 21, 12, 23, 9, 17], [19, 4, 13, 1, 15, 5, 19]],
[[15, 5, 19, 4, 13, 6, 21, 12, 23, 9, 17, 3, 15]],
[[19, 10, 21, 6, 13, 4, 19], [22, 12, 23, 9, 17, 7, 22]],
[[15, 1, 13, 2, 17, 3, 15], [14, 4, 19, 10, 21, 6, 14], [23, 9, 18, 7, 22, 12, 23]],
[[21, 6, 13, 1, 15, 5, 19, 10, 21], [22, 12, 23, 9, 17, 7, 22]],
[[19, 10, 21, 6, 13, 2, 17, 3, 15, 5, 19], [23, 9, 18, 7, 22, 12, 23]],
[[23, 9, 17, 2, 13, 4, 19, 10, 21, 12, 23]],
[[19, 10, 21, 12, 23, 9, 17, 3, 15, 1, 13, 4, 19]],
[[15, 5, 19, 10, 21, 12, 23, 9, 17, 2, 13, 1, 15]],
[[19, 10, 21, 12, 23, 9, 17, 3, 15, 5, 19]],
[[15, 3, 17, 7, 21, 12, 23, 8, 15]],
[[21, 12, 23, 8, 15, 1, 13, 2, 17, 7, 21]],
[[16, 3, 17, 7, 21, 12, 23, 8, 16], [15, 5, 19, 4, 13, 1, 15]],
[[19, 4, 13, 2, 17, 7, 21, 12, 23, 8, 15, 5, 19]],
[[23, 8, 15, 3, 17, 2, 13, 6, 21, 12, 23]],
[[23, 8, 15, 1, 13, 6, 21, 12, 23]],
[[23, 8, 16, 3, 17, 2, 14, 6, 21, 12, 23], [19, 4, 13, 1, 15, 5, 19]],
[[23, 8, 15, 5, 19, 4, 13, 6, 21, 12, 23]],
[[17, 7, 22, 12, 23, 8, 15, 3, 17], [19, 10, 21, 6, 13, 4, 19]],
[[22, 12, 23, 8, 15, 1, 13, 2, 17, 7, 22], [14, 4, 19, 10, 21, 6, 14]],
[[13, 1, 15, 5, 19, 10, 21, 6, 13], [16, 3, 17, 7, 22, 12, 23, 8, 16]],
[[19, 10, 21, 6, 13, 2, 17, 7, 22, 12, 23, 8, 15, 5, 19]],
[[23, 8, 15, 3, 17, 2, 13, 4, 19, 10, 21, 12, 23]],
[[21, 12, 23, 8, 15, 1, 13, 4, 19, 10, 21]],
[[15, 5, 19, 10, 21, 12, 23, 8, 16, 3, 17, 2, 13, 1, 15]],
[[23, 8, 15, 5, 19, 10, 21, 12, 23]],
[[23, 11, 19, 5, 15, 8, 23], [21, 12, 24, 9, 17, 7, 21]],
[[15, 1, 13, 2, 17, 3, 15], [19, 5, 16, 8, 23, 11, 19], [18, 7, 21, 12, 24, 9, 18]],
[[15, 8, 23, 11, 19, 4, 13, 1, 15], [21, 12, 24, 9, 17, 7, 21]],
[[23, 11, 19, 4, 13, 2, 17, 3, 15, 8, 23], [18, 7, 21, 12, 24, 9, 18]],
[[24, 9, 17, 2, 13, 6, 21, 12, 24], [23, 11, 19, 5, 15, 8, 23]],
[[21, 12, 24, 9, 17, 3, 15, 1, 13, 6, 21], [19, 5, 16, 8, 23, 11, 19]],
[[13, 1, 15, 8, 23, 11, 19, 4, 13], [17, 2, 14, 6, 21, 12, 24, 9, 17]],
[[23, 11, 19, 4, 13, 6, 21, 12, 24, 9, 17, 3, 15, 8, 23]],
[[13, 4, 19, 10, 21, 6, 13], [20, 5, 15, 8, 23, 11, 20], [17, 7, 22, 12, 24, 9, 17]],
[[13, 2, 17, 3, 15, 1, 13], [21, 6, 14, 4, 19, 10, 21], [16, 8, 23, 11, 20, 5, 16], [24, 9, 18, 7, 22, 12, 24]],
[[15, 8, 23, 11, 19, 10, 21, 6, 13, 1, 15], [17, 7, 22, 12, 24, 9, 17]],
[[19, 10, 21, 6, 13, 2, 17, 3, 15, 8, 23, 11, 19], [24, 9, 18, 7, 22, 12, 24]],
[[24, 9, 17, 2, 13, 4, 19, 10, 21, 12, 24], [20, 5, 15, 8, 23, 11, 20]],
[[19, 10, 21, 12, 24, 9, 17, 3, 15, 1, 13, 4, 19], [16, 8, 23, 11, 20, 5, 16]],
[[15, 8, 23, 11, 19, 10, 21, 12, 24, 9, 17, 2, 13, 1, 15]],
[[19, 10, 21, 12, 24, 9, 17, 3, 15, 8, 23, 11, 19]],
[[17, 7, 21, 12, 23, 11, 19, 5, 15, 3, 17]],
[[23, 11, 19, 5, 15, 1, 13, 2, 17, 7, 21, 12, 23]],
[[19, 4, 13, 1, 15, 3, 17, 7, 21, 12, 23, 11, 19]],
[[23, 11, 19, 4, 13, 2, 17, 7, 21, 12, 23]],
[[13, 6, 21, 12, 23, 11, 19, 5, 15, 3, 17, 2, 13]],
[[21, 12, 23, 11, 19, 5, 15, 1, 13, 6, 21]],
[[19, 4, 13, 1, 15, 3, 17, 2, 14, 6, 21, 12, 23, 11, 19]],
[[13, 6, 21, 12, 23, 11, 19, 4, 13]],
[[17, 7, 22, 12, 23, 11, 20, 5, 15, 3, 17], [13, 4, 19, 10, 21, 6, 13]],
[[23, 11, 20, 5, 15, 1, 13, 2, 17, 7, 22, 12, 23], [21, 6, 14, 4, 19, 10, 21]],
[[21, 6, 13, 1, 15, 3, 17, 7, 22, 12, 23, 11, 19, 10, 21]],
[[23, 11, 19, 10, 21, 6, 13, 2, 17, 7, 22, 12, 23]],
[[13, 4, 19, 10, 21, 12, 23, 11, 20, 5, 15, 3, 17, 2, 13]],
[[21, 12, 23, 11, 20, 5, 15, 1, 13, 4, 19, 10, 21]],
[[17, 2, 13, 1, 15, 3, 17], [23, 11, 19, 10, 21, 12, 23]],
[[23, 11, 19, 10, 21, 12, 23]],
[[19, 11, 23, 12, 21, 10, 19]],
[[13, 2, 17, 3, 15, 1, 13], [19, 11, 23, 12, 21, 10, 19]],
[[15, 5, 19, 4, 13, 1, 15], [20, 11, 23, 12, 21, 10, 20]],
[[19, 4, 13, 2, 17, 3, 15, 5, 19], [20, 11, 23, 12, 21, 10, 20]],
[[21, 7, 17, 2, 13, 6, 21], [23, 12, 22, 10, 19, 11, 23]],
[[13, 6, 21, 7, 17, 3, 15, 1, 13], [23, 12, 22, 10, 19, 11, 23]],
[[13, 1, 15, 5, 19, 4, 13], [17, 2, 14, 6, 21, 7, 17], [20, 11, 23, 12, 22, 10, 20]],
[[21, 7, 17, 3, 15, 5, 19, 4, 13, 6, 21], [20, 11, 23, 12, 22, 10, 20]],
[[13, 4, 19, 11, 23, 12, 21, 6, 13]],
[[14, 4, 19, 11, 23, 12, 21, 6, 14], [13, 2, 17, 3, 15, 1, 13]],
[[23, 12, 21, 6, 13, 1, 15, 5, 19, 11, 23]],
[[17, 3, 15, 5, 19, 11, 23, 12, 21, 6, 13, 2, 17]],
[[19, 11, 23, 12, 21, 7, 17, 2, 13, 4, 19]],
[[17, 3, 15, 1, 13, 4, 19, 11, 23, 12, 21, 7, 17]],
[[21, 7, 17, 2, 13, 1, 15, 5, 19, 11, 23, 12, 21]],
[[21, 7, 17, 3, 15, 5, 19, 11, 23, 12, 21]],
[[17, 9, 23, 8, 15, 3, 17], [24, 12, 21, 10, 19, 11, 24]],
[[23, 8, 15, 1, 13, 2, 17, 9, 23], [24, 12, 21, 10, 19, 11, 24]],
[[13, 1, 15, 5, 19, 4, 13], [16, 3, 17, 9, 23, 8, 16], [21, 10, 20, 11, 24, 12, 21]],
[[17, 9, 23, 8, 15, 5, 19, 4, 13, 2, 17], [21, 10, 20, 11, 24, 12, 21]],
[[17, 2, 13, 6, 21, 7, 17], [15, 3, 18, 9, 23, 8, 15], [22, 10, 19, 11, 24, 12, 22]],
[[23, 8, 15, 1, 13, 6, 21, 7, 17, 9, 23], [22, 10, 19, 11, 24, 12, 22]],
[[19, 4, 13, 1, 15, 5, 19], [14, 6, 21, 7, 17, 2, 14], [23, 8, 16, 3, 18, 9, 23], [20, 11, 24, 12, 22, 10, 20]],
[[21, 7, 17, 9, 23, 8, 15, 5, 19, 4, 13, 6, 21], [20, 11, 24, 12, 22, 10, 20]],
[[19, 11, 24, 12, 21, 6, 13, 4, 19], [17, 9, 23, 8, 15, 3, 17]],
[[15, 1, 13, 2, 17, 9, 23, 8, 15], [14, 4, 19, 11, 24, 12, 21, 6, 14]],
[[24, 12, 21, 6, 13, 1, 15, 5, 19, 11, 24], [16, 3, 17, 9, 23, 8, 16]],
[[17, 9, 23, 8, 15, 5, 19, 11, 24, 12, 21, 6, 13, 2, 17]],
[[19, 11, 24, 12, 21, 7, 17, 2, 13, 4, 19], [15, 3, 18, 9, 23, 8, 15]],
[[23, 8, 15, 1, 13, 4, 19, 11, 24, 12, 21, 7, 17, 9, 23]],
[[21, 7, 17, 2, 13, 1, 15, 5, 19, 11, 24, 12, 21], [23, 8, 16, 3, 18, 9, 23]],
[[21, 7, 17, 9, 23, 8, 15, 5, 19, 11, 24, 12, 21]],
[[19, 5, 15, 8, 23, 12, 21, 10, 19]],
[[19, 5, 16, 8, 23, 12, 21, 10, 19], [17, 3, 15, 1, 13, 2, 17]],
[[23, 12, 21, 10, 19, 4, 13, 1, 15, 8, 23]],
[[13, 2, 17, 3, 15, 8, 23, 12, 21, 10, 19, 4, 13]],
[[22, 10, 19, 5, 15, 8, 23, 12, 22], [21, 7, 17, 2, 13, 6, 21]],
[[15, 1, 13, 6, 21, 7, 17, 3, 15], [19, 5, 16, 8, 23, 12, 22, 10, 19]],
[[23, 12, 22, 10, 19, 4, 13, 1, 15, 8, 23], [17, 2, 14, 6, 21, 7, 17]],
[[21, 7, 17, 3, 15, 8, 23, 12, 22, 10, 19, 4, 13, 6, 21]],
[[15, 8, 23, 12, 21, 6, 13, 4, 19, 5, 15]],
[[16, 8, 23, 12, 21, 6, 14, 4, 19, 5, 16], [13, 2, 17, 3, 15, 1, 13]],
[[15, 8, 23, 12, 21, 6, 13, 1, 15]],
[[15, 8, 23, 12, 21, 6, 13, 2, 17, 3, 15]],
[[17, 2, 13, 4, 19, 5, 15, 8, 23, 12, 21, 7, 17]],
[[17, 3, 15, 1, 13, 4, 19, 5, 16, 8, 23, 12, 21, 7, 17]],
[[23, 12, 21, 7, 17, 2, 13, 1, 15, 8, 23]],
[[15, 8, 23, 12, 21, 7, 17, 3, 15]],
[[21, 10, 19, 5, 15, 3, 17, 9, 23, 12, 21]],
[[13, 2, 17, 9, 23, 12, 21, 10, 19, 5, 15, 1, 13]],
[[17, 9, 23, 12, 21, 10, 19, 4, 13, 1, 15, 3, 17]],
[[17, 9, 23, 12, 21, 10, 19, 4, 13, 2, 17]],
[[22, 10, 19, 5, 15, 3, 18, 9, 23, 12, 22], [17, 2, 13, 6, 21, 7, 17]],
[[13, 6, 21, 7, 17, 9, 23, 12, 22, 10, 19, 5, 15, 1, 13]],
[[18, 9, 23, 12, 22, 10, 19, 4, 13, 1, 15, 3, 18], [14, 6, 21, 7, 17, 2, 14]],
[[17, 9, 23, 12, 22, 10, 19, 4, 13, 6, 21, 7, 17]],
[[15, 3, 17, 9, 23, 12, 21, 6, 13, 4, 19, 5, 15]],
[[13, 2, 17, 9, 23, 12, 21, 6, 14, 4, 19, 5, 15, 1, 13]],
[[23, 12, 21, 6, 13, 1, 15, 3, 17, 9, 23]],
[[21, 6, 13, 2, 17, 9, 23, 12, 21]],
[[17, 2, 13, 4, 19, 5, 15, 3, 18, 9, 23, 12, 21, 7, 17]],
[[17, 9, 23, 12, 21, 7, 17], [13, 4, 19, 5, 15, 1, 13]],
[[23, 12, 21, 7, 17, 2, 13, 1, 15, 3, 18, 9, 23]],
[[17, 9, 23, 12, 21, 7, 17]],
[[17, 7, 21, 10, 19, 11, 23, 9, 17]],
[[18, 7, 21, 10, 19, 11, 23, 9, 18], [17, 3, 15, 1, 13, 2, 17]],
[[21, 10, 20, 11, 23, 9, 17, 7, 21], [15, 5, 19, 4, 13, 1, 15]],
[[13, 2, 17, 3, 15, 5, 19, 4, 13], [18, 7, 21, 10, 20, 11, 23, 9, 18]],
[[19, 11, 23, 9, 17, 2, 13, 6, 21, 10, 19]],
[[15, 1, 13, 6, 21, 10, 19, 11, 23, 9, 17, 3, 15]],
[[20, 11, 23, 9, 17, 2, 14, 6, 21, 10, 20], [13, 1, 15, 5, 19, 4, 13]],
[[15, 5, 19, 4, 13, 6, 21, 10, 20, 11, 23, 9, 17, 3, 15]],
[[23, 9, 17, 7, 21, 6, 13, 4, 19, 11, 23]],
[[23, 9, 18, 7, 21, 6, 14, 4, 19, 11, 23], [15, 1, 13, 2, 17, 3, 15]],
[[13, 1, 15, 5, 19, 11, 23, 9, 17, 7, 21, 6, 13]],
[[17, 3, 15, 5, 19, 11, 23, 9, 18, 7, 21, 6, 13, 2, 17]],
[[23, 9, 17, 2, 13, 4, 19, 11, 23]],
[[23, 9, 17, 3, 15, 1, 13, 4, 19, 11, 23]],
[[19, 11, 23, 9, 17, 2, 13, 1, 15, 5, 19]],
[[23, 9, 17, 3, 15, 5, 19, 11, 23]],
[[21, 10, 19, 11, 23, 8, 15, 3, 17, 7, 21]],
[[15, 1, 13, 2, 17, 7, 21, 10, 19, 11, 23, 8, 15]],
[[21, 10, 20, 11, 23, 8, 16, 3, 17, 7, 21], [13, 1, 15, 5, 19, 4, 13]],
[[19, 4, 13, 2, 17, 7, 21, 10, 20, 11, 23, 8, 15, 5, 19]],
[[23, 8, 15, 3, 17, 2, 13, 6, 21, 10, 19, 11, 23]],
[[23, 8, 15, 1, 13, 6, 21, 10, 19, 11, 23]],
[[23, 8, 16, 3, 17, 2, 14, 6, 21, 10, 20, 11, 23], [19, 4, 13, 1, 15, 5, 19]],
[[23, 8, 15, 5, 19, 4, 13, 6, 21, 10, 20, 11, 23]],
[[15, 3, 17, 7, 21, 6, 13, 4, 19, 11, 23, 8, 15]],
[[15, 1, 13, 2, 17, 7, 21, 6, 14, 4, 19, 11, 23, 8, 15]],
[[13, 1, 15, 5, 19, 11, 23, 8, 16, 3, 17, 7, 21, 6, 13]],
[[23, 8, 15, 5, 19, 11, 23], [21, 6, 13, 2, 17, 7, 21]],
[[19, 11, 23, 8, 15, 3, 17, 2, 13, 4, 19]],
[[13, 4, 19, 11, 23, 8, 15, 1, 13]],
[[19, 11, 23, 8, 16, 3, 17, 2, 13, 1, 15, 5, 19]],
[[23, 8, 15, 5, 19, 11, 23]],
[[17, 7, 21, 10, 19, 5, 15, 8, 23, 9, 17]],
[[18, 7, 21, 10, 19, 5, 16, 8, 23, 9, 18], [15, 1, 13, 2, 17, 3, 15]],
[[13, 1, 15, 8, 23, 9, 17, 7, 21, 10, 19, 4, 13]],
[[13, 2, 17, 3, 15, 8, 23, 9, 18, 7, 21, 10, 19, 4, 13]],
[[17, 2, 13, 6, 21, 10, 19, 5, 15, 8, 23, 9, 17]],
[[15, 1, 13, 6, 21, 10, 19, 5, 16, 8, 23, 9, 17, 3, 15]],
[[13, 1, 15, 8, 23, 9, 17, 2, 14, 6, 21, 10, 19, 4, 13]],
[[13, 6, 21, 10, 19, 4, 13], [15, 8, 23, 9, 17, 3, 15]],
[[15, 8, 23, 9, 17, 7, 21, 6, 13, 4, 19, 5, 15]],
[[16, 8, 23, 9, 18, 7, 21, 6, 14, 4, 19, 5, 16], [13, 2, 17, 3, 15, 1, 13]],
[[15, 8, 23, 9, 17, 7, 21, 6, 13, 1, 15]],
[[15, 8, 23, 9, 18, 7, 21, 6, 13, 2, 17, 3, 15]],
[[23, 9, 17, 2, 13, 4, 19, 5, 15, 8, 23]],
[[23, 9, 17, 3, 15, 1, 13, 4, 19, 5, 16, 8, 23]],
[[17, 2, 13, 1, 15, 8, 23, 9, 17]],
[[15, 8, 23, 9, 17, 3, 15]],
[[17, 7, 21, 10, 19, 5, 15, 3, 17]],
[[17, 7, 21, 10, 19, 5, 15, 1, 13, 2, 17]],
[[21, 10, 19, 4, 13, 1, 15, 3, 17, 7, 21]],
[[17, 7, 21, 10, 19, 4, 13, 2, 17]],
[[21, 10, 19, 5, 15, 3, 17, 2, 13, 6, 21]],
[[19, 5, 15, 1, 13, 6, 21, 10, 19]],
[[21, 10, 19, 4, 13, 1, 15, 3, 17, 2, 14, 6, 21]],
[[13, 6, 21, 10, 19, 4, 13]],
[[17, 7, 21, 6, 13, 4, 19, 5, 15, 3, 17]],
[[17, 7, 21, 6, 14, 4, 19, 5, 15, 1, 13, 2, 17]],
[[15, 3, 17, 7, 21, 6, 13, 1, 15]],
[[21, 6, 13, 2, 17, 7, 21]],
[[15, 3, 17, 2, 13, 4, 19, 5, 15]],
[[13, 4, 19, 5, 15, 1, 13]],
[[17, 2, 13, 1, 15, 3, 17]],
[]
];
vitogi = [
[0, 0, 0, -1],
[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 2], [0, 0, 1, 1], [0, 0, 1, 2], [0, 1, 0, 0],
[0, 1, 0, 2], [1, 0, 0, 0], [1, 0, 0, 1], [0, 1, 1, 2], [1, 0, 1, 1], [1, 1, 0, 0],
[0, 0, 0, 3], [0, 0, 0, 4], [0, 0, 0, 5], [0, 0, 0, 6], [0, 0, 0, 7], [0, 0, 0, 8],
[0, 0, 1, 7], [0, 0, 1, 8], [0, 1, 0, 5], [0, 1, 0, 6], [1, 0, 0, 3], [1, 0, 0, 4],
[0, 0, 0, 9], [0, 0, 0, 10], [0, 0, 0, 11], [0, 0, 0, 12]
];
lctab_2d = [
[],
[[0, 0, 1], [0, 0, 0]],
[[0, 0, 1], [0, 1, 0]],
[[0, 0, 0], [0, 1, 0]],
[[0, 0, 0], [1, 0, 1]],
[[0, 0, 1], [1, 0, 1]],
[[0, 0, 1], [0, 1, 0], [0, 0, 0], [1, 0, 1]],
[[0, 1, 0], [1, 0, 1]],
[[0, 1, 0], [1, 0, 1]],
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [1, 0, 1]],
[[0, 0, 1], [1, 0, 1]],
[[0, 0, 0], [1, 0, 1]],
[[0, 0, 0], [0, 1, 0]],
[[0, 0, 1], [0, 1, 0]],
[[0, 0, 1], [0, 0, 0]],
[]
];
cstrtab = [
[6, [[0, 5, 3]], [[0, 3, 6]]],
[9, [[1, 2, 4]], [[1, 7, 2]]],
[18, [[0, 5, 3]], [[0, 6, 5]]],
[20, [[0, 3, 6]], [[0, 6, 5]]],
[22, [[0, 5, 3]], [[0, 3, 6]], [[0, 6, 5]]],
[24, [[0, 6, 5]], [[1, 7, 2]]],
[25, [[4, 1, 2], [5, 0, 6]], [[1, 7, 2]]],
[26, [[3, 0, 5], [2, 1, 7]], [[0, 6, 5]]],
[28, [[3, 6, 0], [1, 7, 2]], [[0, 6, 5]]],
[30, [[0, 5, 3]], [[0, 6, 5]]],
[33, [[1, 2, 4]], [[1, 4, 7]]],
[36, [[0, 3, 6]], [[1, 4, 7]]],
[37, [[2, 4, 1], [3, 6, 0]], [[1, 4, 7]]],
[38, [[5, 3, 0], [4, 7, 1]], [[0, 3, 6]]],
[40, [[1, 7, 2]], [[1, 4, 7]]],
[41, [[1, 2, 4]], [[1, 7, 2]], [[1, 4, 7]]],
[44, [[2, 1, 7], [0, 3, 6]], [[1, 4, 7]]],
[45, [[1, 2, 4]], [[1, 4, 7]]],
[52, [[5, 0, 6], [1, 4, 7]], [[0, 3, 6]]],
[54, [[0, 5, 3]], [[0, 3, 6]]],
[56, [[4, 7, 1], [0, 6, 5]], [[1, 7, 2]]],
[57, [[1, 2, 4]], [[1, 7, 2]]],
[60, [[3, 6, 0], [1, 7, 2]], [[0, 6, 5], [1, 4, 7]]],
[61, [[1, 2, 7], [4, 1, 7]]],
[62, [[0, 6, 3], [5, 6, 0]]],
[65, [[2, 4, 1]], [[2, 7, 4]]],
[66, [[0, 5, 3]], [[2, 7, 4]]],
[67, [[1, 2, 4], [3, 0, 5]], [[2, 7, 4]]],
[70, [[6, 0, 3], [4, 2, 7]], [[0, 5, 3]]],
[72, [[2, 1, 7]], [[2, 7, 4]]],
[73, [[2, 4, 1]], [[2, 1, 7]], [[2, 7, 4]]],
[74, [[1, 7, 2], [0, 5, 3]], [[2, 7, 4]]],
[75, [[2, 4, 1]], [[2, 7, 4]]],
[82, [[6, 5, 0], [2, 7, 4]], [[0, 5, 3]]],
[86, [[0, 3, 6]], [[0, 5, 3]]],
[88, [[4, 2, 7], [0, 6, 5]], [[2, 1, 7]]],
[89, [[2, 4, 1]], [[2, 1, 7]]],
[90, [[3, 0, 5], [2, 1, 7]], [[0, 6, 5], [2, 7, 4]]],
[91, [[2, 7, 1], [4, 7, 2]]],
[94, [[0, 3, 5], [6, 0, 5]]],
[96, [[4, 7, 1]], [[4, 2, 7]]],
[97, [[4, 1, 2]], [[4, 7, 1]], [[4, 2, 7]]],
[98, [[1, 4, 7], [0, 5, 3]], [[4, 2, 7]]],
[99, [[4, 1, 2]], [[4, 2, 7]]],
[100, [[2, 7, 4], [0, 3, 6]], [[4, 7, 1]]],
[101, [[4, 1, 2]], [[4, 7, 1]]],
[102, [[5, 3, 0], [4, 7, 1]], [[0, 3, 6], [4, 2, 7]]],
[103, [[4, 1, 7], [2, 4, 7]]],
[104, [[7, 2, 1]], [[7, 1, 4]], [[7, 4, 2]]],
[105, [[1, 2, 4]], [[1, 7, 2]], [[1, 4, 7]], [[2, 7, 4]]],
[106, [[7, 2, 1]], [[7, 4, 2]]],
[107, [[2, 4, 1]], [[2, 7, 4]]],
[108, [[7, 2, 1]], [[7, 1, 4]]],
[109, [[1, 2, 4]], [[1, 4, 7]]],
[110, [[7, 4, 1], [2, 4, 7]]],
[111, [[1, 7, 4], [2, 4, 7]]],
[118, [[0, 3, 5], [6, 3, 0]]],
[120, [[7, 1, 4]], [[7, 2, 1]]],
[121, [[1, 2, 4]], [[1, 7, 2]]],
[122, [[7, 1, 2], [4, 7, 2]]],
[123, [[1, 2, 7], [4, 7, 2]]],
[124, [[7, 1, 2], [4, 1, 7]]],
[125, [[2, 7, 1], [4, 1, 7]]],
[126, [[1, 2, 4]], [[3, 5, 6]]],
[129, [[1, 2, 4]], [[3, 5, 6]]],
[130, [[3, 0, 5]], [[3, 5, 6]]],
[131, [[0, 5, 3], [2, 4, 1]], [[3, 5, 6]]],
[132, [[3, 6, 0]], [[3, 5, 6]]],
[133, [[0, 3, 6], [1, 2, 4]], [[3, 5, 6]]],
[134, [[3, 0, 5]], [[3, 6, 0]], [[3, 5, 6]]],
[135, [[3, 0, 5]], [[3, 5, 6]]],
[137, [[7, 2, 1], [5, 6, 3]], [[1, 2, 4]]],
[144, [[5, 0, 6]], [[5, 6, 3]]],
[145, [[0, 6, 5], [1, 2, 4]], [[5, 6, 3]]],
[146, [[5, 3, 0]], [[5, 0, 6]], [[5, 6, 3]]],
[147, [[5, 3, 0]], [[5, 6, 3]]],
[148, [[6, 0, 3]], [[6, 5, 0]], [[6, 3, 5]]],
[149, [[6, 0, 3]], [[6, 3, 5]]],
[150, [[0, 5, 3]], [[0, 3, 6]], [[0, 6, 5]], [[3, 5, 6]]],
[151, [[3, 0, 5]], [[3, 5, 6]]],
[152, [[3, 5, 6], [1, 7, 2]], [[5, 0, 6]]],
[153, [[4, 1, 2], [5, 0, 6]], [[1, 7, 2], [5, 6, 3]]],
[154, [[5, 3, 0]], [[5, 0, 6]]],
[155, [[5, 6, 0], [3, 6, 5]]],
[156, [[6, 0, 3]], [[6, 5, 0]]],
[157, [[6, 0, 5], [3, 6, 5]]],
[158, [[0, 5, 3]], [[0, 6, 5]]],
[159, [[0, 5, 6], [3, 6, 5]]],
[161, [[7, 1, 4], [3, 5, 6]], [[1, 2, 4]]],
[164, [[5, 6, 3], [1, 4, 7]], [[3, 6, 0]]],
[165, [[2, 4, 1], [3, 6, 0]], [[1, 4, 7], [3, 5, 6]]],
[166, [[3, 0, 5]], [[3, 6, 0]]],
[167, [[3, 0, 6], [5, 3, 6]]],
[169, [[1, 7, 2]], [[1, 2, 4]]],
[173, [[1, 4, 2], [7, 4, 1]]],
[180, [[6, 5, 0]], [[6, 0, 3]]],
[181, [[6, 3, 0], [5, 3, 6]]],
[182, [[0, 5, 3]], [[0, 3, 6]]],
[183, [[0, 6, 3], [5, 3, 6]]],
[185, [[1, 4, 2], [7, 1, 2]]],
[188, [[6, 3, 0], [5, 6, 0]]],
[189, [[2, 7, 4]], [[0, 5, 3]]],
[190, [[3, 0, 6], [5, 6, 0]]],
[193, [[7, 4, 2], [3, 5, 6]], [[2, 4, 1]]],
[194, [[6, 3, 5], [2, 7, 4]], [[3, 0, 5]]],
[195, [[1, 2, 4], [3, 0, 5]], [[2, 7, 4], [3, 5, 6]]],
[198, [[3, 6, 0]], [[3, 0, 5]]],
[199, [[3, 5, 0], [6, 5, 3]]],
[201, [[2, 1, 7]], [[2, 4, 1]]],
[203, [[2, 1, 4], [7, 2, 4]]],
[210, [[5, 0, 6]], [[5, 3, 0]]],
[211, [[5, 0, 3], [6, 5, 3]]],
[214, [[0, 3, 6]], [[0, 5, 3]]],
[215, [[0, 3, 5], [6, 5, 3]]],
[217, [[2, 1, 4], [7, 1, 2]]],
[218, [[5, 0, 3], [6, 0, 5]]],
[219, [[1, 4, 7]], [[0, 3, 6]]],
[222, [[3, 5, 0], [6, 0, 5]]],
[225, [[4, 7, 1]], [[4, 1, 2]]],
[227, [[4, 2, 1], [7, 2, 4]]],
[229, [[4, 2, 1], [7, 4, 1]]],
[230, [[3, 5, 0], [6, 3, 0]]],
[231, [[1, 7, 2]], [[0, 6, 5]]],
[233, [[1, 7, 2]], [[1, 2, 4]]],
[235, [[1, 4, 2], [7, 2, 4]]],
[237, [[2, 1, 4], [7, 4, 1]]],
[246, [[5, 0, 3], [6, 3, 0]]],
[249, [[4, 2, 1], [7, 1, 2]]]
];
cpnttab = [
[6, [4, 4, 20], [4, 20, 4]],
[9, [4, 4, 4], [4, 20, 20]],
[18, [4, 4, 20], [20, 4, 4]],
[20, [4, 20, 4], [20, 4, 4]],
[22, [4, 4, 20], [4, 20, 4], [20, 4, 4]],
[24, [20, 4, 4], [4, 20, 20]],
[25, [12, 3, 3], [4, 20, 20]],
[26, [3, 12, 21], [20, 4, 4]],
[28, [3, 21, 12], [20, 4, 4]],
[30, [4, 4, 20], [20, 4, 4]],
[33, [4, 4, 4], [20, 4, 20]],
[36, [4, 20, 4], [20, 4, 20]],
[37, [3, 12, 3], [20, 4, 20]],
[38, [12, 3, 21], [4, 20, 4]],
[40, [4, 20, 20], [20, 4, 20]],
[41, [4, 4, 4], [4, 20, 20], [20, 4, 20]],
[44, [3, 21, 12], [20, 4, 20]],
[45, [4, 4, 4], [20, 4, 20]],
[52, [21, 3, 12], [4, 20, 4]],
[54, [4, 4, 20], [4, 20, 4]],
[56, [21, 3, 12], [4, 20, 20]],
[57, [4, 4, 4], [4, 20, 20]],
[60, [3, 21, 12], [21, 3, 12]],
[65, [4, 4, 4], [20, 20, 4]],
[66, [4, 4, 20], [20, 20, 4]],
[67, [3, 3, 12], [20, 20, 4]],
[70, [12, 21, 3], [4, 4, 20]],
[72, [4, 20, 20], [20, 20, 4]],
[73, [4, 4, 4], [4, 20, 20], [20, 20, 4]],
[74, [3, 12, 21], [20, 20, 4]],
[75, [4, 4, 4], [20, 20, 4]],
[82, [21, 12, 3], [4, 4, 20]],
[86, [4, 20, 4], [4, 4, 20]],
[88, [21, 12, 3], [4, 20, 20]],
[89, [4, 4, 4], [4, 20, 20]],
[90, [3, 12, 21], [21, 12, 3]],
[96, [20, 4, 20], [20, 20, 4]],
[97, [4, 4, 4], [20, 4, 20], [20, 20, 4]],
[98, [12, 3, 21], [20, 20, 4]],
[99, [4, 4, 4], [20, 20, 4]],
[100, [12, 21, 3], [20, 4, 20]],
[101, [4, 4, 4], [20, 4, 20]],
[102, [12, 3, 21], [12, 21, 3]],
[104, [4, 20, 20], [20, 4, 20], [20, 20, 4]],
[105, [4, 4, 4], [4, 20, 20], [20, 4, 20], [20, 20, 4]],
[106, [4, 20, 20], [20, 20, 4]],
[107, [4, 4, 4], [20, 20, 4]],
[108, [4, 20, 20], [20, 4, 20]],
[109, [4, 4, 4], [20, 4, 20]],
[120, [20, 4, 20], [4, 20, 20]],
[121, [4, 4, 4], [4, 20, 20]],
[126, [4, 4, 4], [20, 20, 20]],
[129, [4, 4, 4], [20, 20, 20]],
[130, [4, 4, 20], [20, 20, 20]],
[131, [3, 3, 12], [20, 20, 20]],
[132, [4, 20, 4], [20, 20, 20]],
[133, [3, 12, 3], [20, 20, 20]],
[134, [4, 4, 20], [4, 20, 4], [20, 20, 20]],
[135, [4, 4, 20], [20, 20, 20]],
[137, [12, 21, 21], [4, 4, 4]],
[144, [20, 4, 4], [20, 20, 20]],
[145, [12, 3, 3], [20, 20, 20]],
[146, [4, 4, 20], [20, 4, 4], [20, 20, 20]],
[147, [4, 4, 20], [20, 20, 20]],
[148, [4, 20, 4], [20, 4, 4], [20, 20, 20]],
[149, [4, 20, 4], [20, 20, 20]],
[150, [4, 4, 20], [4, 20, 4], [20, 4, 4], [20, 20, 20]],
[151, [4, 4, 20], [20, 20, 20]],
[152, [12, 21, 21], [20, 4, 4]],
[153, [12, 3, 3], [12, 21, 21]],
[154, [4, 4, 20], [20, 4, 4]],
[156, [4, 20, 4], [20, 4, 4]],
[158, [4, 4, 20], [20, 4, 4]],
[161, [21, 12, 21], [4, 4, 4]],
[164, [21, 12, 21], [4, 20, 4]],
[165, [3, 12, 3], [21, 12, 21]],
[166, [4, 4, 20], [4, 20, 4]],
[169, [4, 20, 20], [4, 4, 4]],
[180, [20, 4, 4], [4, 20, 4]],
[182, [4, 4, 20], [4, 20, 4]],
[189, [20, 20, 4], [4, 4, 20]],
[193, [21, 21, 12], [4, 4, 4]],
[194, [21, 21, 12], [4, 4, 20]],
[195, [3, 3, 12], [21, 21, 12]],
[198, [4, 20, 4], [4, 4, 20]],
[201, [4, 20, 20], [4, 4, 4]],
[210, [20, 4, 4], [4, 4, 20]],
[214, [4, 20, 4], [4, 4, 20]],
[219, [20, 4, 20], [4, 20, 4]],
[225, [20, 4, 20], [4, 4, 4]],
[231, [4, 20, 20], [20, 4, 4]],
[233, [4, 20, 20], [4, 4, 4]]
];
ambtab = [
[61, 0, 0, 1],
[62, 0, 0, -1],
[91, 0, 1, 0],
[94, 0, -1, 0],
[103, 1, 0, 0],
[110, 1, 0, 0],
[111, 1, 0, 0],
[118, -1, 0, 0],
[122, 0, 1, 0],
[123, 0, 1, 0],
[124, 0, 0, 1],
[125, 0, 0, 1],
[155, 1, 0, 0],
[157, 1, 0, 0],
[159, 1, 0, 0],
[167, 0, 1, 0],
[173, 0, -1, 0],
[181, 0, 1, 0],
[183, 0, 1, 0],
[185, -1, 0, 0],
[188, 0, 0, -1],
[190, 0, 0, -1],
[199, 0, 0, 1],
[203, 0, 0, -1],
[211, 0, 0, 1],
[215, 0, 0, 1],
[217, -1, 0, 0],
[218, 0, -1, 0],
[222, 0, -1, 0],
[227, 0, 0, -1],
[229, 0, -1, 0],
[230, -1, 0, 0],
[235, 0, 0, -1],
[237, 0, -1, 0],
[246, -1, 0, 0],
[249, -1, 0, 0]
];
axd_tab = [[1, 2], [1, 2], [0, 2], [0, 2], [0, 1], [0, 1]];
ax0_tab = [[0, 1, 0], [0, 1, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]];
ax1_tab = [[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0]];
cas_tab = [0, 2, 0, 2, 0, 2];
import torch as th
class occupancy_dual_contouring:
def __init__(self, device):
self.device = device;
self.vitogi = th.tensor(vitogi, dtype = th.int64, device = device);
for a in lctab_2d: a += [[-1, -1, -1]] * (4 - len(a));
self.lctab_2d = th.tensor(lctab_2d, dtype = th.int64, device = device);
for a in pfvtab:
for b in a: b += [0] * (15 - len(b));
a += [[0] * 15] * (4 - len(a));
self.pfvtab = th.tensor(pfvtab, dtype = th.int64, device = device);
self.qvntab = th.div(th.sum(self.pfvtab > 0, dim = 2), 2, rounding_mode = 'floor');
self.vtstab = th.sort(self.pfvtab.reshape(256, -1), dim = 1)[0][:, -32:];
for i in range(4): self.vtstab[self.qvntab[:, i] > 0, i] = 25 + i;
self.vbitab = th.zeros((256, 12), dtype = th.int64, device = device);
for i in range(12):
tmp = th.sum(self.pfvtab == i + 1, dim = 2);
for j in range(4): self.vbitab[tmp[:, j] > 0, i] = j + 9;
self.cstrtab = [[] for i in range(256)];
for a in cstrtab: self.cstrtab[a[0]] = a[1:];
for a in self.cstrtab: a += [[[0, 2, 1]]] * (4 - len(a));
for a in self.cstrtab:
for b in a: b += [[0, 2, 1]] * (2 - len(b));
tmp = th.tensor(self.cstrtab, dtype = th.int64, device = device);
self.cstrtab = th.stack((th.div(tmp, 4, rounding_mode = 'floor'),
th.div(tmp, 2, rounding_mode = 'floor') % 2,
tmp % 2), dim = 4).to(th.float64);
self.cpnttab = [[] for i in range(256)];
for a in cpnttab: self.cpnttab[a[0]] = a[1:];
for a in self.cpnttab: a += [[12, 12, 12]] * (4 - len(a));
self.cpnttab = th.tensor(self.cpnttab, dtype = th.float64, device = device) / 24.0;
self.ambtab = [[0, 0, 0, 0] for _ in range(256)];
for a in ambtab: self.ambtab[a[0]] = [1, a[1], a[2], a[3]];
self.ambtab = th.tensor(self.ambtab, dtype = th.int64, device = device);
self.axd_tab = th.tensor(axd_tab, dtype = th.int64, device = device);
self.ax0_tab = th.tensor(ax0_tab, dtype = th.int64, device = device);
self.ax1_tab = th.tensor(ax1_tab, dtype = th.int64, device = device);
self.cas_tab = th.tensor(cas_tab, dtype = th.int64, device = device);
@th.no_grad()
def extract_mesh(
self,
imp_func,
min_coord: list[float] = [-0.5, -0.5, -0.5],
max_coord: list[float] = [ 0.5, 0.5, 0.5],
num_grid: int = 128,
isolevel: float = 0.0,
batch_size: int = 100000000,
imp_func_cplx: int = 3,
outside: bool = True,
BINARY_SEARCH: int = 15,
VERTICAL_RANGE: float = 0.8,
VERTICAL_LINEAR_SEARCH: int = 4,
VERTICAL_BINARY_SEARCH: int = 11,
HORIZNTL_RANGE: float = 0.71,
HORIZNTL_LINEAR_SEARCH: int = 3,
HORIZNTL_BINARY_SEARCH: int = 12,
ERR: float = 3e-7,
SEP: float = 1e-3,
QEF_REG: float = 0.05
):
GRID = num_grid;
GRID_ = GRID + 1;
GRID2_, GRID3_ = GRID_ ** 2, GRID_ ** 3;
device = self.device;
min_coordc = th.tensor(min_coord, dtype = th.float64, device = device).reshape(1, 3);
siz_coordc = th.tensor(max_coord, dtype = th.float64, device = device).reshape(1, 3) - min_coordc;
B = max(1, batch_size // imp_func_cplx);
if outside: get_occv_ = lambda x: imp_func(x) < isolevel;
else: get_occv_ = lambda x: imp_func(x) > isolevel;
pidx1_to_pidx3 = lambda pi1: th.remainder(th.stack((th.div(pi1, GRID2_, rounding_mode = 'floor'),
th.div(pi1, GRID_, rounding_mode = 'floor'), pi1), dim = -1), GRID_);
pidx3_to_pnts = lambda pi3: (pi3 / GRID).to(th.float64);
def get_occv(cor_):
if cor_.shape[0] == 0:
return th.zeros((0,), dtype = th.bool, device = device);
cor = min_coordc + cor_ * siz_coordc;
if cor.shape[0] <= B: return get_occv_(cor);
out = [];
for cal_i in range(0, cor.shape[0], B):
out.append(get_occv_(cor[cal_i: cal_i + B]));
return th.cat(out, dim = 0);
pidx1 = th.arange(GRID3_, dtype = th.int64, device = device);
occs = get_occv(pidx3_to_pnts(pidx1_to_pidx3(pidx1))).reshape(GRID_, GRID_, GRID_);
vals = th.zeros((GRID, GRID, GRID), dtype = th.uint8, device = device);
vals += occs[ 1:, 1:, 1:]; vals <<= 1;
vals += occs[ 1:, 1:, :-1]; vals <<= 1;
vals += occs[ 1:, :-1, 1:]; vals <<= 1;
vals += occs[ 1:, :-1, :-1]; vals <<= 1;
vals += occs[:-1, 1:, 1:]; vals <<= 1;
vals += occs[:-1, 1:, :-1]; vals <<= 1;
vals += occs[:-1, :-1, 1:]; vals <<= 1;
vals += occs[:-1, :-1, :-1];
cel_pidx3 = th.argwhere((vals > 0) & (vals < 255));
val_ = vals[cel_pidx3[:, 0], cel_pidx3[:, 1], cel_pidx3[:, 2]].to(th.int64);
ambres = self.ambtab[val_];
amb_idcs = th.argwhere(ambres[:, 0] == 1).reshape(-1);
amb_pidx3 = cel_pidx3[amb_idcs] + ambres[amb_idcs, 1:];
tpi = th.argwhere(th.sum((0 <= amb_pidx3) & (amb_pidx3 < GRID), dim = 1) == 3).reshape(-1);
tmp = vals[amb_pidx3[tpi, 0], amb_pidx3[tpi, 1], amb_pidx3[tpi, 2]].to(th.int64);
amb_pidx3 = amb_pidx3[tpi[self.ambtab[tmp, 0] == 1]];
tmp = vals[amb_pidx3[:, 0], amb_pidx3[:, 1], amb_pidx3[:, 2]];
vals[amb_pidx3[:, 0], amb_pidx3[:, 1], amb_pidx3[:, 2]] = 255 - tmp;
amb_chks = th.zeros((GRID_, GRID_, GRID_), dtype = th.bool, device = device);
amb_chks[amb_pidx3[:, 0], amb_pidx3[:, 1], amb_pidx3[:, 2]] = True;
val_ = vals[cel_pidx3[:, 0], cel_pidx3[:, 1], cel_pidx3[:, 2]].to(th.int64);
if cel_pidx3.shape[0] == 0:
print("Occupancy Dual Contouring: No Surface Detected.");
return th.zeros((0, 3), dtype = th.float64, device = device), \
th.zeros((0, 3), dtype = th.int64, device = device);
vtcs = self.vtstab[val_];
sel_pidx1 = self.vitogi[vtcs, 3] * GRID3_ + \
(cel_pidx3[:, 0:1] + self.vitogi[vtcs, 0]) * GRID2_ + \
(cel_pidx3[:, 1:2] + self.vitogi[vtcs, 1]) * GRID_ + \
(cel_pidx3[:, 2:3] + self.vitogi[vtcs, 2]);
sel_pidx1 = sel_pidx1.reshape(-1);
sel_pidx1 = th.unique(sel_pidx1[sel_pidx1 >= 0]);
val_pnts = th.zeros((sel_pidx1.shape[0], 3), dtype = th.float64, device = device);
def get_idx(q):
S = q.shape; q_ = q.reshape(-1);
std, idx = th.unique(th.cat((q_, sel_pidx1), dim = 0), return_inverse = True);
return idx[:q_.shape[0]].reshape(S);
def _1d_search(pidx3, axis, val_):
P = pidx3.shape[0];
pnts = pidx3_to_pnts(pidx3);
left = th.zeros((P, 1), dtype = th.float64, device = device);
rght = th.ones((P, 1), dtype = th.float64, device = device);
for _ in range(BINARY_SEARCH):
mid = (left + rght) * 0.5;
occv = get_occv(pnts + axis * (mid / GRID));
jdge = (occv == val_).unsqueeze(1);
left = th.where(jdge, mid, left);
rght = th.where(jdge, rght, mid);
return left * axis;
start_idx = 0;
pidx1 = sel_pidx1[(0 * GRID3_ <= sel_pidx1) & (sel_pidx1 < 3 * GRID3_)];
count_idx = pidx1.shape[0];
axis = th.zeros((count_idx, 3), dtype = th.float64, device = device);
axis[(0 * GRID3_ <= pidx1) & (pidx1 < 1 * GRID3_), 2] = 1.0;
axis[(1 * GRID3_ <= pidx1) & (pidx1 < 2 * GRID3_), 1] = 1.0;
axis[(2 * GRID3_ <= pidx1) & (pidx1 < 3 * GRID3_), 0] = 1.0;
pidx3 = pidx1_to_pidx3(pidx1);
val_ = occs[pidx3[:, 0], pidx3[:, 1], pidx3[:, 2]];
val_pnts[start_idx: start_idx + count_idx] = _1d_search(pidx3, axis, val_);
start_idx += count_idx;
def _2d_linbin(pnts, spnt, locc, axis, srch_range, lin_step, bin_step):
P = pnts.shape[0];
tstep = srch_range / lin_step;
lidx = th.full((P,), lin_step, dtype = th.int64, device = device);
locc = locc.reshape(-1);
for lin_i in range(lin_step):
cor_ = pnts + (spnt + axis * ((lin_step - lin_i) * tstep)) / GRID;
occv = get_occv(cor_);
lidx = th.where(occv != locc, lin_step - lin_i - 1, lidx);
left = spnt + axis * (lidx.unsqueeze(1) * tstep);
rght = left + axis * tstep;
locc = locc.unsqueeze(1);
for bin_i in range(bin_step):
mid = (left + rght) * 0.5;
occv = get_occv(pnts + mid / GRID).unsqueeze(1);
jdge = locc == occv;
left = th.where(jdge, mid, left);
rght = th.where(jdge, rght, mid);
return left;
def _2d_search(pidx3, axdir, axis0, axis1, val_, cases):
P = pidx3.shape[0];
arng = th.arange(P, dtype = th.int64, device = device);
pnts = pidx3_to_pnts(pidx3);
axis0, axis1 = axis0.to(th.float64), axis1.to(th.float64);
cidx3 = pidx3.clone();
lcres = self.lctab_2d[val_, cases];
cidx3[arng, axdir[:, 0]] += lcres[:, 0];
cidx3[arng, axdir[:, 1]] += lcres[:, 1];
edir = axdir[arng, lcres[:, 2]];
cidx1 = (2 - edir) * GRID3_ + cidx3[:, 0] * GRID2_ + cidx3[:, 1] * GRID_ + cidx3[:, 2];
linv = val_pnts[get_idx(cidx1)];
lcord = th.where(lcres[:, 2:] == 0, linv, axis0 * lcres[:, 0: 1]) + \
th.where(lcres[:, 2:] == 1, linv, axis1 * lcres[:, 1: 2]);
chk0 = cidx3.clone();
occ0 = occs[chk0[:, 0], chk0[:, 1], chk0[:, 2]].unsqueeze(1);
chk0 = (chk0 - pidx3).to(th.float64);
chk1 = cidx3.clone(); chk1[arng, edir] += 1;
occ1 = occs[chk1[:, 0], chk1[:, 1], chk1[:, 2]].unsqueeze(1);
chk1 = (chk1 - pidx3).to(th.float64);
cidx3 = pidx3.clone();
lcres = self.lctab_2d[val_, cases + 1];
cidx3[arng, axdir[:, 0]] += lcres[:, 0];
cidx3[arng, axdir[:, 1]] += lcres[:, 1];
edir = axdir[arng, lcres[:, 2]];
cidx1 = (2 - edir) * GRID3_ + cidx3[:, 0] * GRID2_ + cidx3[:, 1] * GRID_ + cidx3[:, 2];
linv = val_pnts[get_idx(cidx1)];
rcord = th.where(lcres[:, 2:] == 0, linv, axis0 * lcres[:, 0: 1]) + \
th.where(lcres[:, 2:] == 1, linv, axis1 * lcres[:, 1: 2]);
chk2 = cidx3.clone();
occ2 = occs[chk2[:, 0], chk2[:, 1], chk2[:, 2]].unsqueeze(1);
chk2 = (chk2 - pidx3).to(th.float64);
chk3 = cidx3.clone(); chk3[arng, edir] += 1;
occ3 = occs[chk3[:, 0], chk3[:, 1], chk3[:, 2]].unsqueeze(1);
chk3 = (chk3 - pidx3).to(th.float64);
spnt = (lcord + rcord) * 0.5;
locc = get_occv(pnts + spnt / GRID).unsqueeze(1);
hnorm = lcord - rcord;
leng = th.norm(hnorm, dim = 1, keepdim = True);
cndt = leng < ERR;
leng[cndt] = 1.0;
hnorm = hnorm / leng;
vnorm = th.cross(th.cross(axis0, axis1, dim = 1), hnorm, dim = 1);
tmp = th.sum((chk0 - spnt) * vnorm, dim = 1, keepdim = True);
vnorm = th.where((th.abs(tmp) > ERR) & th.bitwise_xor(tmp > 0, locc != occ0), -vnorm, vnorm);
tmp = th.sum((chk1 - spnt) * vnorm, dim = 1, keepdim = True);
vnorm = th.where((th.abs(tmp) > ERR) & th.bitwise_xor(tmp > 0, locc != occ1), -vnorm, vnorm);
tmp = th.sum((chk2 - spnt) * vnorm, dim = 1, keepdim = True);
vnorm = th.where((th.abs(tmp) > ERR) & th.bitwise_xor(tmp > 0, locc != occ2), -vnorm, vnorm);
tmp = th.sum((chk3 - spnt) * vnorm, dim = 1, keepdim = True);
vnorm = th.where((th.abs(tmp) > ERR) & th.bitwise_xor(tmp > 0, locc != occ3), -vnorm, vnorm);
left = _2d_linbin(pnts, spnt, locc, vnorm,
VERTICAL_RANGE, VERTICAL_LINEAR_SEARCH, VERTICAL_BINARY_SEARCH);
vl = th.sum((left - spnt) * vnorm, dim = 1, keepdim = True);
cndt |= th.abs(vl) < ERR;
lleft = _2d_linbin(pnts, left, locc, hnorm,
HORIZNTL_RANGE, HORIZNTL_LINEAR_SEARCH, HORIZNTL_BINARY_SEARCH) - lcord;
lh = th.sum(lleft * hnorm, dim = 1, keepdim = True);
rleft = _2d_linbin(pnts, left, locc, -hnorm,
HORIZNTL_RANGE, HORIZNTL_LINEAR_SEARCH, HORIZNTL_BINARY_SEARCH) - rcord;
rh = th.sum(rleft * hnorm, dim = 1, keepdim = True);
denm = rh - lh;
cndt |= th.abs(denm) < ERR;
rslt = ((0.5 * (rh + lh)) * hnorm + vl * vnorm) * (leng / denm);
cndt |= th.sum(rslt * vnorm, dim = 1, keepdim = True) < 0;
rslt = th.where(cndt, th.zeros_like(rslt), rslt);
return spnt + rslt;
pidx1 = sel_pidx1[(3 * GRID3_ <= sel_pidx1) & (sel_pidx1 < 9 * GRID3_)];
count_idx = pidx1.shape[0];
csidx = th.div(pidx1, GRID3_, rounding_mode = 'floor') - 3;
axdir = self.axd_tab[csidx];
axis0 = self.ax0_tab[csidx];
axis1 = self.ax1_tab[csidx];
cases = self.cas_tab[csidx];
axis2 = axis0 + axis1;
pidx3 = pidx1_to_pidx3(pidx1);
val_ = occs[pidx3[:, 0] , pidx3[:, 1] , pidx3[:, 2] ] + \
2 * occs[pidx3[:, 0] + axis1[:, 0], pidx3[:, 1] + axis1[:, 1], pidx3[:, 2] + axis1[:, 2]] + \
4 * occs[pidx3[:, 0] + axis0[:, 0], pidx3[:, 1] + axis0[:, 1], pidx3[:, 2] + axis0[:, 2]] + \
8 * occs[pidx3[:, 0] + axis2[:, 0], pidx3[:, 1] + axis2[:, 1], pidx3[:, 2] + axis2[:, 2]];
tmp = amb_chks[pidx3[:, 0], pidx3[:, 1], pidx3[:, 2]];
val_[tmp] = 15 - val_[tmp];
val_pnts[start_idx: start_idx + count_idx] = _2d_search(pidx3, axdir, axis0, axis1, val_, cases);
start_idx += count_idx;
def _solve_QEF(pidx3, val_, cases):
out = th.zeros((pidx3.shape[0], 3), dtype = th.float64, device = device);
for i in range(3, 8):
idx = th.argwhere(self.qvntab[val_, cases] == i).reshape(-1);
pid3_ = pidx3[idx]; val0_ = val_[idx]; cas = cases[idx];
vtcs = self.pfvtab[val0_, cas, :2 * i + 1];
vitg = self.vitogi[vtcs];
pnti = vitg[:, :, 3] * GRID3_ + \
(pid3_[:, 0:1] + vitg[:, :, 0]) * GRID2_ + \
(pid3_[:, 1:2] + vitg[:, :, 1]) * GRID_ + \
(pid3_[:, 2:3] + vitg[:, :, 2]);
pidx = get_idx(pnti);
vert = val_pnts[pidx];
vert += vitg[:, :, :3];
_1vt = vert[:, 1::2];
qnrm = th.cross(_1vt - vert[:, :-1:2], _1vt - vert[:, 2::2], dim = 2);
cntr = th.mean(_1vt, dim = 1);
anrm = th.norm(qnrm, dim = 2, keepdim = True);
cndt = anrm < ERR;
qnrm /= th.where(cndt, th.ones_like(anrm), anrm);
cndt = th.sum(cndt, dim = 1) == cndt.shape[1];
eye_ = th.eye(3, dtype = th.float64, device = device).view(1, 3, 3).repeat(cntr.shape[0], 1, 1);
qefr = th.linalg.lstsq(th.cat((qnrm, QEF_REG * eye_), dim = 1),
th.cat((th.sum(_1vt * qnrm, dim = 2, keepdim = True),
QEF_REG * cntr.unsqueeze(2)), dim = 1)).solution.reshape(-1, 3);
qefr = th.where(cndt, cntr, qefr);
cpnt = self.cpnttab[val0_, cas];
ctoq = qefr - cpnt;
leng = th.norm(ctoq, dim = 1, keepdim = True);
cscd = self.cstrtab[val0_, cas];
cvtx = cscd[:, :, 0];
cnml = th.cross(cscd[:, :, 2] - cvtx, cscd[:, :, 1] - cvtx, dim = 2);
t = th.sum(cnml * (cvtx - cpnt.unsqueeze(1)), dim = 2) / th.sum(cnml * ctoq.unsqueeze(1), dim = 2);
t = th.cat(((1.0 - cpnt) / ctoq, -cpnt / ctoq, t), dim = 1) * leng;
cndt = (t < 0) | th.isnan(t);
t[cndt] = leng.repeat(1, 8)[cndt] + SEP;
t = (t - SEP) / th.where(leng < ERR, th.ones_like(leng), leng);
t = th.min(th.clamp(t, 0.0, 1.0), dim = 1, keepdim = True)[0];
out[idx] = cpnt + t * ctoq;
return out;
pidx1 = sel_pidx1[9 * GRID3_ <= sel_pidx1];
count_idx = pidx1.shape[0];
pidx3 = pidx1_to_pidx3(pidx1);
val_ = vals[pidx3[:, 0], pidx3[:, 1], pidx3[:, 2]].to(th.int64);
cases = th.div(pidx1, GRID3_, rounding_mode = 'floor') - 9;
val_pnts[start_idx: start_idx + count_idx] = _solve_QEF(pidx3, val_, cases);
start_idx += count_idx;
def _get_face():
faces = [];
cndts, vidcs, vpnts = [], [], [];
evofs = [];
idcs = th.tensor([[[12], [8], [6], [1]],
[[11], [4], [9], [2]],
[[10], [7], [5], [3]]], dtype = th.int64, device = device);
ofst = th.tensor([[[0], [GRID_ ], [GRID2_], [GRID2_ + GRID_]],
[[0], [GRID2_], [1 ], [GRID2_ + 1 ]],
[[0], [1 ], [GRID_ ], [1 + GRID_]]],
dtype = th.int64, device = device);
vofs = th.tensor([[[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0], [1, 1, 0]],
[[0, 0, 0], [1, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 1]],
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [0, 1, 1]]],
dtype = th.int64, device = device).unsqueeze(2);
z, y, x = th.argwhere(th.bitwise_xor(occs[1:-1, 1:-1, :-1], occs[1:-1, 1:-1, 1:])).T;
val_ = vals[z.unsqueeze(0) + vofs[0, :4, 0, 0:1],
y.unsqueeze(0) + vofs[0, :4, 0, 1:2],
x.unsqueeze(0) + vofs[0, :4, 0, 2:3]].to(th.int64);
fac_idx = (z * GRID2_ + y * GRID_ + x).unsqueeze(0);
vidx3 = self.vbitab[val_, idcs[0] - 1] * GRID3_ + fac_idx + ofst[0];
gvidx = get_idx(th.cat((vidx3, fac_idx + (GRID2_ + GRID_)), dim = 0));
gvpnt = val_pnts[gvidx] + vofs[0].to(th.float64);
cndts.append(occs[z + 1, y + 1, x + 1]);
vidcs.append(gvidx.clone());
vpnts.append(gvpnt.clone());
evofs.append(vofs[0, 4].repeat(x.shape[0], 1));
z, y, x = th.argwhere(th.bitwise_xor(occs[1:-1, :-1, 1:-1], occs[1:-1, 1:, 1:-1])).T;
val_ = vals[z.unsqueeze(0) + vofs[1, :4, 0, 0:1],
y.unsqueeze(0) + vofs[1, :4, 0, 1:2],
x.unsqueeze(0) + vofs[1, :4, 0, 2:3]].to(th.int64);
fac_idx = (z * GRID2_ + y * GRID_ + x).unsqueeze(0);
vidx3 = self.vbitab[val_, idcs[1] - 1] * GRID3_ + fac_idx + ofst[1];
gvidx = get_idx(th.cat((vidx3, fac_idx + (GRID3_ + GRID2_ + 1)), dim = 0));
gvpnt = val_pnts[gvidx] + vofs[1].to(th.float64);
cndts.append(occs[z + 1, y + 1, x + 1]);
vidcs.append(gvidx.clone());
vpnts.append(gvpnt.clone());
evofs.append(vofs[1, 4].repeat(x.shape[0], 1));
z, y, x = th.argwhere(th.bitwise_xor(occs[:-1, 1:-1, 1:-1], occs[1:, 1:-1, 1:-1])).T;
val_ = vals[z.unsqueeze(0) + vofs[2, :4, 0, 0:1],
y.unsqueeze(0) + vofs[2, :4, 0, 1:2],
x.unsqueeze(0) + vofs[2, :4, 0, 2:3]].to(th.int64);
fac_idx = (z * GRID2_ + y * GRID_ + x).unsqueeze(0);
vidx3 = self.vbitab[val_, idcs[2] - 1] * GRID3_ + fac_idx + ofst[2];
gvidx = get_idx(th.cat((vidx3, fac_idx + (2 * GRID3_ + 1 + GRID_)), dim = 0));
gvpnt = val_pnts[gvidx] + vofs[2].to(th.float64);
cndts.append(occs[z + 1, y + 1, x + 1]);
vidcs.append(gvidx.clone());
vpnts.append(gvpnt.clone());
evofs.append(vofs[2, 4].repeat(x.shape[0], 1));
cndts, vidcs, vpnts = th.cat(cndts, dim = 0), th.cat(vidcs, dim = 1), th.cat(vpnts, dim = 1);
evofs = th.cat(evofs, dim = 0).to(th.float64).unsqueeze(0);
idcs = th.tensor([0, 1, 3, 2, 0, 1], dtype = th.int64, device = device);