Project

General

Profile

Download (6.62 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / touchcontrol / TouchControlDodecahedron.java @ 369e6176

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.touchcontrol;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.SQ5;
13

    
14
import org.distorted.library.type.Static3D;
15
import org.distorted.objectlib.main.TwistyObject;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18
// Dodecahedral objects: map the 2D swipes of user's fingers to 3D rotations
19

    
20
public class TouchControlDodecahedron extends TouchControlShapeConstant
21
{
22
  public static final float C2       = (SQ5+3)/4;
23
  public static final float LEN      = (float)(Math.sqrt(1.25f+0.5f*SQ5));
24
  public static final float SIN54    = (SQ5+1)/4;
25
  public static final float COS54    = (float)(Math.sqrt(10-2*SQ5)/4);
26

    
27
  public  static final float DIST3D = (float)Math.sqrt(0.625f+0.275f*SQ5);
28
  private static final float DIST2D = (SIN54/COS54)/2;
29
  public static final float[] D3D   = { DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,
30
                                        DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,DIST3D };
31

    
32
  public static final Static3D[] FACE_AXIS = new Static3D[]
33
         {
34
           new Static3D(    C2/LEN, SIN54/LEN,    0      ),
35
           new Static3D(    C2/LEN,-SIN54/LEN,    0      ),
36
           new Static3D(   -C2/LEN, SIN54/LEN,    0      ),
37
           new Static3D(   -C2/LEN,-SIN54/LEN,    0      ),
38
           new Static3D( 0        ,    C2/LEN, SIN54/LEN ),
39
           new Static3D( 0        ,    C2/LEN,-SIN54/LEN ),
40
           new Static3D( 0        ,   -C2/LEN, SIN54/LEN ),
41
           new Static3D( 0        ,   -C2/LEN,-SIN54/LEN ),
42
           new Static3D( SIN54/LEN,    0     ,    C2/LEN ),
43
           new Static3D( SIN54/LEN,    0     ,   -C2/LEN ),
44
           new Static3D(-SIN54/LEN,    0     ,    C2/LEN ),
45
           new Static3D(-SIN54/LEN,    0     ,   -C2/LEN )
46
         };
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

    
50
  public TouchControlDodecahedron(TwistyObject object)
51
    {
52
    super(object,D3D,FACE_AXIS);
53
    }
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

    
57
  public float returnRotationFactor(int[] numLayers, int row)
58
    {
59
    return 1.0f;
60
    }
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63
// return angle (in radians) that the line connecting the center C of the pentagonal face and the
64
// first vertex of the pentagon makes with a vertical line coming upwards from the center C.
65

    
66
  private float returnAngle(int face)
67
    {
68
    switch(face)
69
      {
70
      case  0:
71
      case  2:
72
      case  6:
73
      case  7: return 0.0f;
74
      case  1:
75
      case  3:
76
      case  4:
77
      case  5: return (float)(36*Math.PI/180);
78
      case  9:
79
      case 10: return (float)(54*Math.PI/180);
80
      case  8:
81
      case 11: return (float)(18*Math.PI/180);
82
      }
83

    
84
    return 0.0f;
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88
// The pair (distance,angle) defines a point P in R^2 in polar coordinate system. Let V be the vector
89
// from the center of the coordinate system to P.
90
// Let P' be the point defined by polar (distance,angle+PI/2). Let Lh be the half-line starting at
91
// P' and going in the direction of V.
92
// Return true iff point 'point' lies on the left of Lh, i.e. when we rotate (using the center of
93
// the coordinate system as the center of rotation) 'point' and Lh in such a way that Lh points
94
// directly upwards, is 'point' on the left or the right of it?
95

    
96
  private boolean isOnTheLeft(float[] point, float distance, float angle)
97
    {
98
    float sin = (float)Math.sin(angle);
99
    float cos = (float)Math.cos(angle);
100

    
101
    float vx = point[0] + sin*distance;
102
    float vy = point[1] - cos*distance;
103

    
104
    return vx*sin < vy*cos;
105
    }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
  int returnPart(int type, int face, float[] point)
110
    {
111
    switch(type)
112
      {
113
      case TYPE_NOT_SPLIT      : return 0;
114
      case TYPE_SPLIT_EDGE     : return partEdge(point,face);
115
      case TYPE_SPLIT_EDGE_COIN: float y = point[1];
116
                                 float x = point[0];
117
                                 float dist = D_PENTA*DIST2D;
118
                                 return partEdge(point,face) + (x*x+y*y < dist*dist ? 0:5 );
119
      case TYPE_SPLIT_CORNER   : // not supported
120
      }
121

    
122
    return 0;
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
// Return 0,1,2,3,4 - the vertex of the pentagon to which point 'point' is the closest, if the
127
// 'point' is inside the pentagon - or -1 otherwise.
128
// The 'first' vertex is the one we meet the first when we rotate clockwise starting from 12:00.
129
// This vertex makes angle 'returnAngle()' with the line coming out upwards from the center of the
130
// pentagon.
131
// Distance from the center to a vertex of the pentagon = 1/(6*COS54)
132

    
133
  private int partEdge(float[] point, int face)
134
    {
135
    float angle = returnAngle(face);
136
    float A = (float)(Math.PI/5);
137

    
138
    for(int i=0; i<5; i++)
139
      {
140
      if( isOnTheLeft(point, DIST2D, (9-2*i)*A-angle) ) return -1;
141
      }
142

    
143
    if( isOnTheLeft(point, 0, 2.5f*A-angle) )
144
      {
145
      if( isOnTheLeft(point, 0, 3.5f*A-angle) )
146
        {
147
        return isOnTheLeft(point, 0, 5.5f*A-angle) ? 3 : 4;
148
        }
149
      else return 0;
150
      }
151
    else
152
      {
153
      if( isOnTheLeft(point, 0, 4.5f*A-angle) )
154
        {
155
        return 2;
156
        }
157
      else
158
        {
159
        return isOnTheLeft(point, 0, 6.5f*A-angle) ? 1 : 0;
160
        }
161
      }
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  boolean isInsideFace(int face, float[] p)
167
    {
168
    float angle = returnAngle(face);
169
    float A = (float)(Math.PI/5);
170

    
171
    for(int i=0; i<5; i++)
172
      {
173
      if( isOnTheLeft(p, DIST2D, (9-2*i)*A-angle) ) return false;
174
      }
175

    
176
    return true;
177
    }
178
}
(4-4/13)