Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / touchcontrol / TouchControlDodecahedron.java @ 57ef6378

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.touchcontrol;
21

    
22
import static org.distorted.objectlib.main.TwistyObject.SQ5;
23

    
24
import org.distorted.library.type.Static3D;
25
import org.distorted.objectlib.main.TwistyObject;
26

    
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// Dodecahedral objects: map the 2D swipes of user's fingers to 3D rotations
29

    
30
public class TouchControlDodecahedron extends TouchControlShapeConstant
31
{
32
  public static final float C2       = (SQ5+3)/4;
33
  public static final float LEN      = (float)(Math.sqrt(1.25f+0.5f*SQ5));
34
  public static final float SIN54    = (SQ5+1)/4;
35
  public static final float COS54    = (float)(Math.sqrt(10-2*SQ5)/4);
36

    
37
  public  static final float DIST3D = (float)Math.sqrt(0.625f+0.275f*SQ5);
38
  private static final float DIST2D = (SIN54/COS54)/2;
39
  private static final float[] D3D  = { DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,
40
                                        DIST3D,DIST3D,DIST3D,DIST3D,DIST3D,DIST3D };
41

    
42
  public static final Static3D[] FACE_AXIS = new Static3D[]
43
         {
44
           new Static3D(    C2/LEN, SIN54/LEN,    0      ),
45
           new Static3D(    C2/LEN,-SIN54/LEN,    0      ),
46
           new Static3D(   -C2/LEN, SIN54/LEN,    0      ),
47
           new Static3D(   -C2/LEN,-SIN54/LEN,    0      ),
48
           new Static3D( 0        ,    C2/LEN, SIN54/LEN ),
49
           new Static3D( 0        ,    C2/LEN,-SIN54/LEN ),
50
           new Static3D( 0        ,   -C2/LEN, SIN54/LEN ),
51
           new Static3D( 0        ,   -C2/LEN,-SIN54/LEN ),
52
           new Static3D( SIN54/LEN,    0     ,    C2/LEN ),
53
           new Static3D( SIN54/LEN,    0     ,   -C2/LEN ),
54
           new Static3D(-SIN54/LEN,    0     ,    C2/LEN ),
55
           new Static3D(-SIN54/LEN,    0     ,   -C2/LEN )
56
         };
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

    
60
  public TouchControlDodecahedron(TwistyObject object)
61
    {
62
    super(object,D3D,FACE_AXIS);
63
    }
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  public float returnRotationFactor(int[] numLayers, int row)
68
    {
69
    return 1.0f;
70
    }
71

    
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73
// return angle (in radians) that the line connecting the center C of the pentagonal face and the
74
// first vertex of the pentagon makes with a vertical line coming upwards from the center C.
75

    
76
  private float returnAngle(int face)
77
    {
78
    switch(face)
79
      {
80
      case  0:
81
      case  2:
82
      case  6:
83
      case  7: return 0.0f;
84
      case  1:
85
      case  3:
86
      case  4:
87
      case  5: return (float)(36*Math.PI/180);
88
      case  9:
89
      case 10: return (float)(54*Math.PI/180);
90
      case  8:
91
      case 11: return (float)(18*Math.PI/180);
92
      }
93

    
94
    return 0.0f;
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
// The pair (distance,angle) defines a point P in R^2 in polar coordinate system. Let V be the vector
99
// from the center of the coordinate system to P.
100
// Let P' be the point defined by polar (distance,angle+PI/2). Let Lh be the half-line starting at
101
// P' and going in the direction of V.
102
// Return true iff point 'point' lies on the left of Lh, i.e. when we rotate (using the center of
103
// the coordinate system as the center of rotation) 'point' and Lh in such a way that Lh points
104
// directly upwards, is 'point' on the left or the right of it?
105

    
106
  private boolean isOnTheLeft(float[] point, float distance, float angle)
107
    {
108
    float sin = (float)Math.sin(angle);
109
    float cos = (float)Math.cos(angle);
110

    
111
    float vx = point[0] + sin*distance;
112
    float vy = point[1] - cos*distance;
113

    
114
    return vx*sin < vy*cos;
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

    
119
  int returnPart(int type, int face, float[] point)
120
    {
121
    switch(type)
122
      {
123
      case TYPE_SPLIT_EDGE  : return partEdge(point,face);
124
      case TYPE_SPLIT_CORNER: return partCorner(point,face);
125
      default               : return 0;
126
      }
127
    }
128

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

    
137
  int partEdge(float[] point, int face)
138
    {
139
    float angle = returnAngle(face);
140
    float A = (float)(Math.PI/5);
141

    
142
    for(int i=0; i<5; i++)
143
      {
144
      if( isOnTheLeft(point, DIST2D, (9-2*i)*A-angle) ) return -1;
145
      }
146

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

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169
// TODO - no such object yet
170

    
171
  int partCorner(float[] point, int face)
172
    {
173
    return 0;
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  boolean isInsideFace(int face, float[] p)
179
    {
180
    float angle = returnAngle(face);
181
    float A = (float)(Math.PI/5);
182

    
183
    for(int i=0; i<5; i++)
184
      {
185
      if( isOnTheLeft(p, DIST2D, (9-2*i)*A-angle) ) return false;
186
      }
187

    
188
    return true;
189
    }
190
}
(3-3/8)