-
Notifications
You must be signed in to change notification settings - Fork 13
/
GK.java
1625 lines (1532 loc) · 43.7 KB
/
GK.java
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
package org.fleen.geom_Kisrhombille;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.fleen.geom_2D.GD;
/*
* KISRHOMBILLE GEOMETRY
*
* General kisrhombille coordinate system constants and methods.
*
* Directions are integers. We have 12, like a clock.
* Vertex has 4 coordinates. TODO reduce to 3
*
*
*
* o V12
* |\
* | \
* | \
* | \ hawk
* goat | \
* | \
* | \
* | \
* V4 o--------o V6
* fish
*
*/
public class GK{
public static final double SQRT3=Math.sqrt(3.0);
public static final int AXISCOUNT=6;
/*
* ################################
* BASIC DIAMOND CONSTANTS AND METRICS
* ################################
*/
public static final boolean
TWIST_POSITIVE=true,
TWIST_NEGATIVE=false;
public static enum Orbit{
CLOCKWISE,
COUNTERCLOCKWISE}
/*
* ++++++++++++++++++++++++++++++++
* VERTEX TYPES
* type values corrospond to dog values
* name index corrosponds to the number of segs that connect at a vertex of that type
* eg : VERTEX12 has 12 connections, VERTEX4A has 4 connections, etc
*/
public static final int
VERTEX_NULL=-1,
VERTEX_12=0,
VERTEX_4A=1,
VERTEX_6A=2,
VERTEX_4B=3,
VERTEX_6B=4,
VERTEX_4C=5;
/*
* ++++++++++++++++++++++++++++++++
* VERTEX GENERAL TYPES
* general type is 4,6 or 12
* it is also the number of edges at the vertex
*/
public static final int
VERTEX_GTYPE_4=0,
VERTEX_GTYPE_6=1,
VERTEX_GTYPE_12=2;
/*
* ++++++++++++++++++++++++++++++++
* EDGE TYPES
* "edge" as in a graph edge
* that is, the connecting lines between vertices
*/
public static final int
EDGE_NULL=-1,EDGE_FISH=0,EDGE_GOAT=1,EDGE_HAWK=2;
/*
* ++++++++++++++++++++++++++++++++
* EDGE STANDARD LENGTH VALUES
* these can be scaled however, of course
*/
public static final double
EDGESLV_FISH=1.0,
EDGESLV_GOAT=Math.sqrt(3.0),
EDGESLV_HAWK=2.0;
/*
* ++++++++++++++++++++++++++++++++
* DIRECTIONS
* For standard grid spin (spin==true) DIRECTION_0 is north and
* they are addressed clockwise.
*/
public static final int
DIRECTION_NULL=-1,
DIRECTION_0=0,
DIRECTION_1=1,
DIRECTION_2=2,
DIRECTION_3=3,
DIRECTION_4=4,
DIRECTION_5=5,
DIRECTION_6=6,
DIRECTION_7=7,
DIRECTION_8=8,
DIRECTION_9=9,
DIRECTION_10=10,
DIRECTION_11=11;
/*
* ++++++++++++++++++++++++++++++++
* 2D VALUES FOR OUR 12 DIRECTIONS
*/
public static final double[] DIRECTION_2D={
(0.0/12.0)*(GD.PI*2.0),
(1.0/12.0)*(GD.PI*2.0),
(2.0/12.0)*(GD.PI*2.0),
(3.0/12.0)*(GD.PI*2.0),
(4.0/12.0)*(GD.PI*2.0),
(5.0/12.0)*(GD.PI*2.0),
(6.0/12.0)*(GD.PI*2.0),
(7.0/12.0)*(GD.PI*2.0),
(8.0/12.0)*(GD.PI*2.0),
(9.0/12.0)*(GD.PI*2.0),
(10.0/12.0)*(GD.PI*2.0),
(11.0/12.0)*(GD.PI*2.0)};
/*
* convert diamond direction to real 2d direciton
*/
public static final double getDirection2D(int d){
if(d<0||d>11)return -1;
return DIRECTION_2D[d];}
/*
* Direction axis types
*/
public static final boolean
DIRECTION_AXIS_HAWK=true,
DIRECTION_AXIS_GOAT=false;
/*
*
*/
public static final boolean getAxisType(int d){
return d%2==0;}
public static final boolean directionAxisIsHawky(int d){
return d%2==0;}
public static final boolean directionAxisIsGoaty(int d){
return d%2==1;}
/*
* normalize arbitrary integer value to range [0,11]
*/
public static final int normalizeDirection(int d){
d=d%12;
if(d<0)d+=12;
return d;}
/*
* ################################
* VERTEX LIBERTIES
* each vertex is connected to the diamond graph via 4, 6 or 12 directions.
* We refer to each of directions as a "liberty".
* herein we describe the set of liberties for each vertex type (indicated by the "dog" coordinate)
* ################################
*/
public static final int[][] VERTEX_LIBERTIES={
{0,1,2,3,4,5,6,7,8,9,10,11},//V12
{2,5,8,11},//V4A
{0,2,4,6,8,10},//V6A
{1,4,7,10},//V4B
{0,2,4,6,8,10},//V6B
{0,3,6,9}};//V4C
public static final int[] getLiberties(int vdog){
return VERTEX_LIBERTIES[vdog];}
/*
* return true if a vertex of the specified type (vdog)
* has liberty in the specified direction.
* false otherwise.
*/
public static final boolean hasLiberty(int vdog,int dir){
for(int i=0;i<VERTEX_LIBERTIES[vdog].length;i++){
if(VERTEX_LIBERTIES[vdog][i]==dir)
return true;}
return false;}
/*
* ################################
* ADJACENT VERTEX
* ################################
*/
/*
* returns null if the specified vertex has no such adjacent in the specified direction
*/
public static final KPoint getVertex_Adjacent(KPoint v,int dir){
int[] v1=new int[4];
getVertex_Adjacent(
v.coors[0],
v.coors[1],
v.coors[2],
v.coors[3],
dir,
v1);
if(v1[3]==VERTEX_NULL)return null;
return new KPoint(v1);}
/*
* Given the specified vertex (v0a,v0b,v0c,v0d) and a direction (dir), return
* the coordinates of the implied adjacent vertex in the v1 array
* if the specified direction indicates an invalid liberty for v0
* then we return VERTEX_NULL in v1[3]
*/
public static final void getVertex_Adjacent(int v0a,int v0b,int v0c,int v0d,int dir,int[] v1){
switch(v0d){
case VERTEX_12:
switch(dir){
case DIRECTION_0:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=2;
return;
case DIRECTION_1:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=3;
return;
case DIRECTION_2:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=4;
return;
case DIRECTION_3:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=5;
return;
case DIRECTION_4:
v1[0]=v0a+1;
v1[1]=v0b;
v1[2]=v0c-1;
v1[3]=2;
return;
case DIRECTION_5:
v1[0]=v0a+1;
v1[1]=v0b;
v1[2]=v0c-1;
v1[3]=1;
return;
case DIRECTION_6:
v1[0]=v0a;
v1[1]=v0b-1;
v1[2]=v0c-1;
v1[3]=4;
return;
case DIRECTION_7:
v1[0]=v0a;
v1[1]=v0b-1;
v1[2]=v0c-1;
v1[3]=3;
return;
case DIRECTION_8:
v1[0]=v0a;
v1[1]=v0b-1;
v1[2]=v0c-1;
v1[3]=2;
return;
case DIRECTION_9:
v1[0]=v0a-1;
v1[1]=v0b-1;
v1[2]=v0c;
v1[3]=5;
return;
case DIRECTION_10:
v1[0]=v0a-1;
v1[1]=v0b-1;
v1[2]=v0c;
v1[3]=4;
return;
case DIRECTION_11:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=1;
return;
default:
v1[3]=VERTEX_NULL;
return;}
case VERTEX_4A:
switch(dir){
case DIRECTION_2:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=2;
return;
case DIRECTION_5:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_8:
v1[0]=v0a-1;
v1[1]=v0b-1;
v1[2]=v0c;
v1[3]=4;
return;
case DIRECTION_11:
v1[0]=v0a-1;
v1[1]=v0b;
v1[2]=v0c+1;
v1[3]=0;
return;
default:
v1[3]=VERTEX_NULL;
return;}
case VERTEX_6A:
switch(dir){
case DIRECTION_0:
v1[0]=v0a-1;
v1[1]=v0b;
v1[2]=v0c+1;
v1[3]=5;
return;
case DIRECTION_2:
v1[0]=v0a;
v1[1]=v0b+1;
v1[2]=v0c+1;
v1[3]=0;
return;
case DIRECTION_4:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=3;
return;
case DIRECTION_6:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_8:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=1;
return;
case DIRECTION_10:
v1[0]=v0a-1;
v1[1]=v0b;
v1[2]=v0c+1;
v1[3]=0;
return;
default:
v1[3]=VERTEX_NULL;
return;}
case VERTEX_4B:
switch(dir){
case DIRECTION_1:
v1[0]=v0a;
v1[1]=v0b+1;
v1[2]=v0c+1;
v1[3]=0;
return;
case DIRECTION_4:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=4;
return;
case DIRECTION_7:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_10:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=2;
return;
default:
v1[3]=VERTEX_NULL;
return;}
case VERTEX_6B:
switch(dir){
case DIRECTION_0:
v1[0]=v0a;
v1[1]=v0b+1;
v1[2]=v0c+1;
v1[3]=0;
return;
case DIRECTION_2:
v1[0]=v0a+1;
v1[1]=v0b+1;
v1[2]=v0c;
v1[3]=1;
return;
case DIRECTION_4:
v1[0]=v0a+1;
v1[1]=v0b+1;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_6:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=5;
return;
case DIRECTION_8:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_10:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=3;
return;
default:
v1[3]=VERTEX_NULL;
return;}
case VERTEX_4C:
switch(dir){
case DIRECTION_0:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=4;
return;
case DIRECTION_3:
v1[0]=v0a+1;
v1[1]=v0b+1;
v1[2]=v0c;
v1[3]=0;
return;
case DIRECTION_6:
v1[0]=v0a+1;
v1[1]=v0b;
v1[2]=v0c-1;
v1[3]=2;
return;
case DIRECTION_9:
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=0;
return;
default:
v1[3]=VERTEX_NULL;
return;}
default:
v1[3]=VERTEX_NULL;
return;}}
/*
* ################################
* VERTEX EDGE TYPES BY DIRECTION
* ################################
*/
/*
* Given a vertex type (vdog) and a direction (dir), get the edge type therein
*/
public static final int getEdgeType(int vdog,int dir){
switch(vdog){
case VERTEX_12:
switch(dir){
case DIRECTION_0:
return EDGE_HAWK;
case DIRECTION_1:
return EDGE_GOAT;
case DIRECTION_2:
return EDGE_HAWK;
case DIRECTION_3:
return EDGE_GOAT;
case DIRECTION_4:
return EDGE_HAWK;
case DIRECTION_5:
return EDGE_GOAT;
case DIRECTION_6:
return EDGE_HAWK;
case DIRECTION_7:
return EDGE_GOAT;
case DIRECTION_8:
return EDGE_HAWK;
case DIRECTION_9:
return EDGE_GOAT;
case DIRECTION_10:
return EDGE_HAWK;
case DIRECTION_11:
return EDGE_GOAT;
default:
return EDGE_NULL;}
case VERTEX_4A:
switch(dir){
case DIRECTION_2:
return EDGE_FISH;
case DIRECTION_5:
return EDGE_GOAT;
case DIRECTION_8:
return EDGE_FISH;
case DIRECTION_11:
return EDGE_GOAT;
default:
return EDGE_NULL;}
case VERTEX_6A:
switch(dir){
case DIRECTION_0:
return EDGE_FISH;
case DIRECTION_2:
return EDGE_HAWK;
case DIRECTION_4:
return EDGE_FISH;
case DIRECTION_6:
return EDGE_HAWK;
case DIRECTION_8:
return EDGE_FISH;
case DIRECTION_10:
return EDGE_HAWK;
default:
return EDGE_NULL;}
case VERTEX_4B:
switch(dir){
case DIRECTION_1:
return EDGE_GOAT;
case DIRECTION_4:
return EDGE_FISH;
case DIRECTION_7:
return EDGE_GOAT;
case DIRECTION_10:
return EDGE_FISH;
default:
return EDGE_NULL;}
case VERTEX_6B:
switch(dir){
case DIRECTION_0:
return EDGE_HAWK;
case DIRECTION_2:
return EDGE_FISH;
case DIRECTION_4:
return EDGE_HAWK;
case DIRECTION_6:
return EDGE_FISH;
case DIRECTION_8:
return EDGE_HAWK;
case DIRECTION_10:
return EDGE_FISH;
default:
return EDGE_NULL;}
case VERTEX_4C:
switch(dir){
case DIRECTION_0:
return EDGE_FISH;
case DIRECTION_3:
return EDGE_GOAT;
case DIRECTION_6:
return EDGE_FISH;
case DIRECTION_9:
return EDGE_GOAT;
default:
return EDGE_NULL;}
default:
return EDGE_NULL;}}
/*
* ################################
* VERTEX, VECTOR, DISTANCE, DIRECTION OPS
* NOTE We don't have to be really optimal or efficient, so we arent. We brute it.
* We will be dealing with distances in the range of 1..20 at most.
* More likely maxing at 5. We do it the easy way. Prolly the faster way too.
* Look at the old code for our old bloated complex universally applicable methods.
* ################################
*/
/**
* Given 2 directions, get the direction of d0 relative to d1
* returns value in range [-5,5]
* throws exception on direction reversal
* TODO just return the -6?
*/
public static final int getDirectionDelta(int d0,int d1){
int delta;
if(d0==d1){//same direction
delta=0;
}else{
//pretend that d0 is 0
int w=(d1+12-d0)%12;
if(w<6){
delta=w;
}else if(w>6){
delta=w-12;
}else{
throw new IllegalArgumentException("BAD GEOMETRY : direction reversal : d0="+d0+" d1="+d1);}}
return delta;}
/*
* ++++++++++++++++++++++++++++++++
* GET DIRECTION VERTEX VERTEX
* ++++++++++++++++++++++++++++++++
*/
private static final double
GETDIRVV_ERROR=1.0/(65596.0*2.0*GD.PI),
DIRECTION_2D_0_ALTERNATE=GD.PI*2.0;
private static final double[][] GETDIRVV_RANGES={
{DIRECTION_2D_0_ALTERNATE-GETDIRVV_ERROR,GETDIRVV_ERROR},
{DIRECTION_2D[1]-GETDIRVV_ERROR,DIRECTION_2D[1]+GETDIRVV_ERROR},
{DIRECTION_2D[2]-GETDIRVV_ERROR,DIRECTION_2D[2]+GETDIRVV_ERROR},
{DIRECTION_2D[3]-GETDIRVV_ERROR,DIRECTION_2D[3]+GETDIRVV_ERROR},
{DIRECTION_2D[4]-GETDIRVV_ERROR,DIRECTION_2D[4]+GETDIRVV_ERROR},
{DIRECTION_2D[5]-GETDIRVV_ERROR,DIRECTION_2D[5]+GETDIRVV_ERROR},
{DIRECTION_2D[6]-GETDIRVV_ERROR,DIRECTION_2D[6]+GETDIRVV_ERROR},
{DIRECTION_2D[7]-GETDIRVV_ERROR,DIRECTION_2D[7]+GETDIRVV_ERROR},
{DIRECTION_2D[8]-GETDIRVV_ERROR,DIRECTION_2D[8]+GETDIRVV_ERROR},
{DIRECTION_2D[9]-GETDIRVV_ERROR,DIRECTION_2D[9]+GETDIRVV_ERROR},
{DIRECTION_2D[10]-GETDIRVV_ERROR,DIRECTION_2D[10]+GETDIRVV_ERROR},
{DIRECTION_2D[11]-GETDIRVV_ERROR,DIRECTION_2D[11]+GETDIRVV_ERROR}};
/*
* Given 2 vertices : v0,v1
* get the direction from v0 to v1
* If the direction is invalid because the 2 vertices are not colinar (coaxial)
* (not one of our 12, within error) then we return DIRECTION_NULL
*/
public static final int getDirection_VertexVertex(
int v0a,int v0b,int v0c,int v0d,int v1a,int v1b,int v1c,int v1d){
//get the direction 2dwise
double[] p0=new double[2],p1=new double[2];
getBasicPoint2D_Vertex(v0a,v0b,v0c,v0d,p0);
getBasicPoint2D_Vertex(v1a,v1b,v1c,v1d,p1);
double d2d=GD.getDirection_PointPoint(p0[0],p0[1],p1[0],p1[1]);
double[] range;
//filter the 2d direction value for gkis direction 0
if(d2d>GETDIRVV_RANGES[0][0]||d2d<GETDIRVV_RANGES[0][1])
return 0;
//filter the 2d direction value for our other 11 gkis directions
for(int i=1;i<12;i++){
range=GETDIRVV_RANGES[i];
if(d2d>range[0]&&d2d<range[1])
return i;}
return DIRECTION_NULL;}
public static final int getDirection_VertexVertex(KPoint v0,KPoint v1){
return getDirection_VertexVertex(
v0.getAnt(),v0.getBat(),v0.getCat(),v0.getDog(),
v1.getAnt(),v1.getBat(),v1.getCat(),v1.getDog());}
// public static final void main(String[] a){
// KVertex v0=new KVertex(-1,2,3,0),v1=new KVertex(-1,1,2,2);
// int dir=getDirection_VertexVertex(v0,v1);
// System.out.println("dir="+dir);
// }
/*
* COLINEARITY TEST
* If the direction from v0 to v1 is a valid one for that particular
* pair of vertex types then v0 and v1 are colinear.
*/
public static final boolean getColinear_VertexVertex(
int v0a,int v0b,int v0c,int v0d,int v1a,int v1b,int v1c,int v1d){
int d=getDirection_VertexVertex(v0a,v0b,v0c,v0d,v1a,v1b,v1c,v1d);
//if null direction then noncolinear
if(d==DIRECTION_NULL)return false;
//we have a valid direction, is it valid for this pair of vertex types?
//that is, is it a shared liberty?
return hasLiberty(v0d,d)&&hasLiberty(v1d,d);}
/*
* ++++++++++++++++++++++++++++++++
* GET DISTANCE VERTEX VERTEX
* simply convert to basic 2d points and use 2d distance
* ++++++++++++++++++++++++++++++++
*/
public static final double getDistance_VertexVertex(
KPoint v0,KPoint v1){
return getDistance_VertexVertex(
v0.getAnt(),v0.getBat(),v0.getCat(),v0.getDog(),
v1.getAnt(),v1.getBat(),v1.getCat(),v1.getDog());}
public static final double getDistance_VertexVertex(
int v0a,int v0b,int v0c,int v0d,int v1a,int v1b,int v1c,int v1d){
double[] p0=new double[2],p1=new double[2];
getBasicPoint2D_Vertex(v0a,v0b,v0c,v0d,p0);
getBasicPoint2D_Vertex(v1a,v1b,v1c,v1d,p1);
return GD.getDistance_PointPoint(p0[0],p0[1],p1[0],p1[1]);}
/*
* ++++++++++++++++++++++++++++++++
* GET VECTOR FROM 2 VERTICES
* ++++++++++++++++++++++++++++++++
*/
public static final KVector getVector_VertexVertex(
int v0a,int v0b,int v0c,int v0d,int v1a,int v1b,int v1c,int v1d){
int dir=getDirection_VertexVertex(v0a,v0b,v0c,v0d,v1a,v1b,v1c,v1d);
//if it's a null direction then bad vector
if(dir==DIRECTION_NULL)return null;
//if the direction is one where either of the vertices has no such liberty then bad vector
if(!(hasLiberty(v0d,dir))&&(hasLiberty(v1d,dir)))return null;
//get distance and that's that
double dis=getDistance_VertexVertex(v0a,v0b,v0c,v0d,v1a,v1b,v1c,v1d);
return new KVector(dir,dis);}
/*
* ++++++++++++++++++++++++++++++++
* GET VERTEX FROM VERTEX AND VECTOR
* Crawl from the specified vertex one adjacent neighbor at a time in
* the specified direction over the specified distance until distance is within error of zero
* if it falls beneath negative error then fail.
* ++++++++++++++++++++++++++++++++
*/
private static final double
GETVERTEXVV_TRAVERSALERRORCEILING=1.0/65536.0,
GETVERTEXVV_TRAVERSALERRORFLOOR=-GETVERTEXVV_TRAVERSALERRORCEILING;
public static final KPoint getVertex_VertexVector(KPoint v,KVector t){
int[] v1=new int[4];
getVertex_VertexVector(v.getAnt(),v.getBat(),v.getCat(),v.getDog(),t.direction,t.distance,v1);
if(v1[3]==VERTEX_NULL)return null;
KPoint vertex=new KPoint(v1);
return vertex;}
public static final int[] getVertex_VertexVector(int[] v0,int tdir,double tdis){
int[] v1=new int[4];
getVertex_VertexVector(v0[0],v0[1],v0[2],v0[3],tdir,tdis,v1);
return v1;}
/*
* return the vertex in v1 as an int[4] of coordinates
* return VERTEX_NULL at dog on fail
*/
public static final void getVertex_VertexVector(
int v0a,int v0b,int v0c,int v0d,int tdir,double tdis,int[] v1){
double remaining=tdis;
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=v0d;
while(remaining>GETVERTEXVV_TRAVERSALERRORCEILING){
remaining-=getAdjacentDistance(v1[3],tdir);
if(remaining<GETVERTEXVV_TRAVERSALERRORFLOOR){
v1[3]=VERTEX_NULL;
return;}
getVertex_Adjacent(v1[0],v1[1],v1[2],v1[3],tdir,v1);
if(v1[3]==VERTEX_NULL){
return;}}}
/*
* given the specified vertex type and direction, get the distance to the vertex adjacent to
* that vertex in that direction.
* we DO NOT check that a vertex with the specified vdog does indeed have a liberty at the specified direction
* so if the specified vertex type does not have a liberty at the specified direction then an ambiguous value
* will be returned
*/
public static final double getAdjacentDistance(int vdog,int dir){
if(dir%2==1)return EDGESLV_GOAT;
switch(vdog){
case VERTEX_12:
return EDGESLV_HAWK;
case VERTEX_4A:
return EDGESLV_FISH;
case VERTEX_6A:
if(dir%4==0){
return EDGESLV_FISH;
}else{
return EDGESLV_HAWK;}
case VERTEX_4B:
return EDGESLV_FISH;
case VERTEX_6B:
if(dir%4==0){
return EDGESLV_HAWK;
}else{
return EDGESLV_FISH;}
case VERTEX_4C:
return EDGESLV_FISH;
default:
throw new IllegalArgumentException("invalid value for vdog : "+vdog);}}
/*
* ++++++++++++++++++++++++++++++++
* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
* TEST
* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
* ++++++++++++++++++++++++++++++++
*/
private static final int TEST_CYCLES_COUNT=10000;
/*
* get a random vertex v0
* get a random vector t
* derive v1 via sequential adjacent process
* derive v1 via getVertex_VertexVector method
* if they match then good
* if they don't then fail
* run it 10000 times or so
* time it too
*/
public static final void TEST_getVertex_VertexVector(){
int[] v0,v1a,v1b,vector;
int failurecount=0;
for(int i=0;i<TEST_CYCLES_COUNT;i++){
v0=getRandomVertex();
vector=getRandomVector(v0);
v1a=new int[4];
v1b=new int[4];
getVertex_VertexVector_AdjProcessForTest(v0[0],v0[1],v0[2],v0[3],vector[0],vector[1],v1a);
getVertex_VertexVector(v0[0],v0[1],v0[2],v0[3],vector[0],vector[1],v1b);
//our derived vertices can match in 2 ways :
// 1) they both express failure (dog==VERTEX_NULL therefor invalid vertex, due to bad distance)
// 2) all of the coordinates match
if(
(v1a[3]==VERTEX_NULL&&v1b[3]==VERTEX_NULL)||
(v1a[0]==v1b[0]&&
v1a[1]==v1b[1]&&
v1a[2]==v1b[2]&&
v1a[3]==v1b[3])){
System.out.println("TEST INDEX : "+i+" : --- SUCCEESS ---");
}else{
failurecount++;
System.out.println("TEST INDEX : "+i+" : ##>> FAIL <<##");
System.out.println("v0 : "+v0[0]+","+v0[1]+","+v0[2]+","+v0[3]);
System.out.println("vector dir : "+vector[0]);
System.out.println("vector dis : "+vector[1]);
System.out.println("v1a : "+v1a[0]+","+v1a[1]+","+v1a[2]+","+v1a[3]);
System.out.println("v1b : "+v1b[0]+","+v1b[1]+","+v1b[2]+","+v1b[3]);
System.out.println("#><##><##><##><##><##><##><##><#");}}
//
if(failurecount==0){
System.out.println("^^^^^^^^^^^^^^");
System.out.println("TEST SUCCEEDED");
System.out.println("TEST CYCLES : "+TEST_CYCLES_COUNT);
System.out.println("^^^^^^^^^^^^^^");
}else{
System.out.println("#><##><##><##><##><##><##><##><#");
System.out.println("TEST FAILED");
System.out.println("TEST CYCLES : "+TEST_CYCLES_COUNT);
System.out.println("FAILURE COUNT : "+failurecount);
System.out.println("#><##><##><##><##><##><##><##><#");}}
/*
* consider our vertex and vector
* traverse adjacent vertices from v0 in direction vector.direction until total distance >= vector.distance
* if 0 was skipped and total distance reached is > vector.distance then we have arrived in the middle of a hawk
* edge. Therefor fail because distances must work out perfectly.
*/
private static final void getVertex_VertexVector_AdjProcessForTest(
int v0a,int v0b,int v0c,int v0d,int tdir,int tdis,int[] v1){
int distancetraversed=0,edgelength;
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;
v1[3]=v0d;
while(distancetraversed<tdis){
edgelength=(getEdgeType(v1[3],tdir)==EDGE_HAWK)?2:1;
getVertex_Adjacent(v1[0],v1[1],v1[2],v1[3],tdir,v1);
distancetraversed+=edgelength;}
//if we have overrun our vector distance then the vertex is invalid
if(distancetraversed>tdis){
v1[3]=VERTEX_NULL;}}
private static final int[] getRandomVertex(){
Random r=new Random();
int
a=r.nextInt(21)-10,
b=r.nextInt(21)-10,
c=b-a,
d=r.nextInt(6);
return new int[]{a,b,c,d};}
private static final int[] getRandomVector(int[] v){
Random r=new Random();
int
dir=VERTEX_LIBERTIES[v[3]][r.nextInt(VERTEX_LIBERTIES[v[3]].length)],
dis=r.nextInt(33)+1;
return new int[]{dir,dis};}
/*
* ################################
* POINT 2D FROM VERTEX
* Given a basic diamond coordinate system (origin=(0,0), twist=true, foreward=0, fish=1),
* translate the specified diamond vertex coordinates into 2d point coordinates
* ################################
*/
private static final double
UINT_1=1.0,
UINT_2=2.0,
UINT_SQRT3=Math.sqrt(3.0),
P2D_G=UINT_SQRT3/2.0,
P2D_H=3.0/2.0;
public static final double[] getBasicPoint2D_Vertex(int[] p){
double[] p2=new double[2];
getBasicPoint2D_Vertex(p[0],p[1],p[2],p[3],p2);
return p2;}
/*
* return the 2d point assuming a standard diamond grid where
* foreward == 0/2PI, fish=1.0 and direction indexing is clockwise.
*/
public static final void getBasicPoint2D_Vertex(int ant,int bat,int cat,int dog,double[] p2d){
//start with coordinates of the v12 at the center of the flower
p2d[0]=(ant+bat)*UINT_SQRT3;
p2d[1]=cat*(UINT_1+UINT_2);
//the other 5 vertices are relative to the V12
switch(dog){
case 0: //V12
break;
case 1: //V4A
p2d[0]-=P2D_G;
p2d[1]+=P2D_H;
break;
case 2: //V6A
p2d[1]+=UINT_2;
break;
case 3: //V4B
p2d[0]+=P2D_G;
p2d[1]+=P2D_H;
break;
case 4: //V6B
p2d[0]+=UINT_SQRT3;
p2d[1]+=UINT_1;
break;
case 5: //V4C
p2d[0]+=UINT_SQRT3;
break;
default:throw new IllegalArgumentException("dog out of range [0,5]. dog=="+dog);}}
/*
* ################################
* GET VERTEX TRANSITIONWISE
* Use an integer transitions count instead of real distance
* ################################
*/
/*
* ++++++++++++++++++++++++++++++++
* get vertex via vertex, direction and transitions
* ++++++++++++++++++++++++++++++++
*/
//dog patterns by direction
private static final int[]
DOGPATTERN0={0,2,5,4},
DOGPATTERN1={0,3,0,3},
DOGPATTERN2={0,4,1,2},
DOGPATTERN3={0,5,0,5},
DOGPATTERN4={0,2,3,4},
DOGPATTERN5={0,1,0,1},
DOGPATTERN6={0,4,5,2},
DOGPATTERN7={0,3,0,3},
DOGPATTERN8={0,2,1,4},
DOGPATTERN9={0,5,0,5},
DOGPATTERN10={0,4,3,2},
DOGPATTERN11={0,1,0,1};
/*
* given a vertex (v0a,v0b,v0c,v0d) a direction (dir) and a transitions count (trans), return the
* implied vertex coordinates in v1.
*/
public static final void getVertex_Transitionswise(
int v0a,int v0b,int v0c,int v0d,int dir,int trans,int[] v1){
//if transitions is 0 then we return the original vertex
if(trans==0){
v1[0]=v0a;
v1[1]=v0b;
v1[2]=v0c;