Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactorySticker.java @ 198c5bf0

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 198c5bf0 Leszek Koltunski
package org.distorted.objectlib.helpers;
21 29b82486 Leszek Koltunski
22
import static org.distorted.objectlib.main.TwistyObject.COLOR_BLACK;
23
import static org.distorted.objectlib.main.TwistyObject.TEXTURE_HEIGHT;
24
25
import android.graphics.Canvas;
26
import android.graphics.Paint;
27
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
30
public class FactorySticker
31
  {
32
  private static FactorySticker mThis;
33
  private float mOX, mOY, mR;
34
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36
37
  private FactorySticker()
38
    {
39
40
    }
41
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43
44
  public static FactorySticker getInstance()
45
    {
46
    if( mThis==null ) mThis = new FactorySticker();
47
48
    return mThis;
49
    }
50
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52
53
  private float computeAngle(float dx, float dy)
54
    {
55
    float PI = (float)Math.PI;
56
    double angle = Math.atan2(dy,dx);
57
    float ret = (float)(3*PI/2-angle);
58
59
    if( ret>2*PI ) ret-= 2*PI;
60
61
    return ret;
62
    }
63
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65
66
  private float getAngle(float[] angles, int index)
67
    {
68
    return angles==null ? 0 : angles[index];
69
    }
70
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72
73
  private void computeCircleCoords(float lX,float lY, float rX, float rY, float alpha)
74
    {
75
    float ctg= 1.0f/((float)Math.tan(alpha));
76
    mOX = 0.5f*(lX+rX) + ctg*0.5f*(lY-rY);
77
    mOY = 0.5f*(lY+rY) - ctg*0.5f*(lX-rX);
78
    float dx = mOX-lX;
79
    float dy = mOY-lY;
80
    mR = (float)Math.sqrt(dx*dx+dy*dy);
81
    }
82
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84
// circle1: center (x1,y1) radius r1; circle2: center (x2,y2) radius r2.
85
// Guaranteed to intersect in two points. Find the intersection. Which one? the one that's closer
86
// to (nearx,neary).
87
88
  private void findCircleIntersection(float x1,float y1, float r1, float x2, float y2, float r2, float nearx, float neary )
89
    {
90
    float dx = x2-x1;
91
    float dy = y2-y1;
92
    float d = (float)Math.sqrt(dx*dx+dy*dy);
93
94
    if( d>0 )
95
      {
96
      float Dx = dx/d;
97
      float Dy = dy/d;
98
      float cos = (r1*r1+d*d-r2*r2)/(2*r1*d);
99
      float sin = (float)Math.sqrt(1-cos*cos);
100
101
      float ox1 = x1 + r1*cos*Dx + r1*sin*Dy;
102
      float oy1 = y1 + r1*cos*Dy - r1*sin*Dx;
103
      float ox2 = x1 + r1*cos*Dx - r1*sin*Dy;
104
      float oy2 = y1 + r1*cos*Dy + r1*sin*Dx;
105
106
      dx = nearx-ox1;
107
      dy = neary-oy1;
108
      float d1 = dx*dx+dy*dy;
109
      dx = nearx-ox2;
110
      dy = neary-oy2;
111
      float d2 = dx*dx+dy*dy;
112
113
      if( d1<d2 )
114
        {
115
        mOX = ox1;
116
        mOY = oy1;
117
        }
118
      else
119
        {
120
        mOX = ox2;
121
        mOY = oy2;
122
        }
123
      }
124
    else
125
      {
126
      mOX = x1;
127
      mOY = y1;
128
      }
129
    }
130
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
133
  private void drawCurrCurveV(Canvas canvas, Paint paint, int left, int top, float r, float stroke, float pX, float pY, float cX, float cY, float nX, float nY, float pA, float cA)
134
    {
135
    pX = (0.5f+pX)*TEXTURE_HEIGHT;
136
    pY = (0.5f-pY)*TEXTURE_HEIGHT;
137
    cX = (0.5f+cX)*TEXTURE_HEIGHT;
138
    cY = (0.5f-cY)*TEXTURE_HEIGHT;
139
    nX = (0.5f+nX)*TEXTURE_HEIGHT;
140
    nY = (0.5f-nY)*TEXTURE_HEIGHT;
141
142
    computeCircleCoords(pX,pY,cX,cY,pA);
143
    float o1x = mOX;
144
    float o1y = mOY;
145
    float r1  = mR;
146
    computeCircleCoords(cX,cY,nX,nY,cA);
147
    float o2x = mOX;
148
    float o2y = mOY;
149
    float r2  = mR;
150
151
    float dx = o1x-pX;
152
    float dy = o1y-pY;
153
    float startA = computeAngle(dy,dx);
154
    float sweepA = 2*pA;
155
156
    startA *= 180/(Math.PI);
157
    sweepA *= 180/(Math.PI);
158
159
    canvas.drawArc( left+o1x-r1, top+o1y-r1, left+o1x+r1, top+o1y+r1, startA, sweepA, false, paint);
160
161
    float r3 = r*TEXTURE_HEIGHT + stroke/2;
162
    float R1 = r1 + (pA < 0 ? r3:-r3);
163
    float R2 = r2 + (cA < 0 ? r3:-r3);
164
    findCircleIntersection(o1x,o1y,R1,o2x,o2y,R2,cX,cY);
165
    float o3x = mOX;
166
    float o3y = mOY;
167
168
    dx = pA<0 ? o3x-o1x : o1x-o3x;
169
    dy = pA<0 ? o3y-o1y : o1y-o3y;
170
    startA = computeAngle(dy,dx);
171
    dx = cA<0 ? o3x-o2x : o2x-o3x;
172
    dy = cA<0 ? o3y-o2y : o2y-o3y;
173
    float endA = computeAngle(dy,dx);
174
175
    sweepA = endA-startA;
176
    if( sweepA<0 ) sweepA += 2*Math.PI;
177
178
    startA *= 180/(Math.PI);
179
    sweepA *= 180/(Math.PI);
180
181
    canvas.drawArc( left+o3x-r3, top+o3y-r3, left+o3x+r3, top+o3y+r3, startA, sweepA, false, paint);
182
    }
183
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185
186
  private void drawCurrVertex(Canvas canvas, Paint paint, int left, int top, float r, float stroke, float pX, float pY, float cX, float cY, float nX, float nY)
187
    {
188
    pX = (0.5f+pX)*TEXTURE_HEIGHT;
189
    pY = (0.5f-pY)*TEXTURE_HEIGHT;
190
    cX = (0.5f+cX)*TEXTURE_HEIGHT;
191
    cY = (0.5f-cY)*TEXTURE_HEIGHT;
192
    nX = (0.5f+nX)*TEXTURE_HEIGHT;
193
    nY = (0.5f-nY)*TEXTURE_HEIGHT;
194
195
    canvas.drawLine(left+pX,top+pY,left+cX,top+cY,paint);
196
197
    float aX = pX-cX;
198
    float aY = pY-cY;
199
    float bX = cX-nX;
200
    float bY = cY-nY;
201
202
    float aLen = (float)Math.sqrt(aX*aX+aY*aY);
203
    float bLen = (float)Math.sqrt(bX*bX+bY*bY);
204
205
    aX /= aLen;
206
    aY /= aLen;
207
    bX /= bLen;
208
    bY /= bLen;
209
210
    float sX = (aX-bX)/2;
211
    float sY = (aY-bY)/2;
212
    float sLen = (float)Math.sqrt(sX*sX+sY*sY);
213
    sX /= sLen;
214
    sY /= sLen;
215
216
    float startAngle = computeAngle(bX,-bY);
217
    float endAngle   = computeAngle(aX,-aY);
218
    float sweepAngle = endAngle-startAngle;
219
    if( sweepAngle<0 ) sweepAngle += 2*Math.PI;
220
221
    float R = r*TEXTURE_HEIGHT+stroke/2;
222
    float C = (float)Math.cos(sweepAngle/2);
223
    float A = R/C;
224
225
    left += (cX+A*sX);
226
    top  += (cY+A*sY);
227
228
    if( C< (2*R-stroke)/(2*R+stroke) )
229
      {
230
      float alpha = startAngle + sweepAngle/2;
231
      float B  = (R-stroke/2)/C;
232
      float sx = (float)Math.cos(alpha);
233
      float sy = (float)Math.sin(alpha);
234
235
      float startX = left + R*sx;
236
      float startY = top  + R*sy;
237
      float stopX  = left + B*sx;
238
      float stopY  = top  + B*sy;
239
240
      canvas.drawLine(startX,startY,stopX,stopY,paint);
241
      }
242
243
    startAngle *= 180/(Math.PI);
244
    sweepAngle *= 180/(Math.PI);
245
246
    canvas.drawArc( left-R, top-R, left+R, top+R, startAngle, sweepAngle, false, paint);
247
    }
248
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250
// PUBLIC
251
252
  public void drawRoundedPolygon(Canvas canvas, Paint paint, int left, int top, int color, ObjectSticker sticker)
253
    {
254
    float stroke = sticker.getStroke();
255
    float[] vertices = sticker.getCoords();
256
    float[] angles = sticker.getCurvature();
257
    float[] radii = sticker.getRadii();
258
259
    stroke *= TEXTURE_HEIGHT;
260
261
    paint.setAntiAlias(true);
262
    paint.setStrokeWidth(stroke);
263
    paint.setColor(color);
264
    paint.setStyle(Paint.Style.FILL);
265
266
    canvas.drawRect(left,top,left+TEXTURE_HEIGHT,top+TEXTURE_HEIGHT,paint);
267
268
    paint.setColor(COLOR_BLACK);
269
    paint.setStyle(Paint.Style.STROKE);
270
271
    int length = vertices.length;
272
    int numVertices = length/2;
273
274
    float prevX = vertices[length-2];
275
    float prevY = vertices[length-1];
276
    float currX = vertices[0];
277
    float currY = vertices[1];
278
    float nextX = vertices[2];
279
    float nextY = vertices[3];
280
281
    float prevA = getAngle(angles,numVertices-1);
282
    float currA = getAngle(angles,0);
283
284
    for(int vert=0; vert<numVertices; vert++)
285
      {
286
      if( prevA==0 )
287
        {
288
        drawCurrVertex(canvas, paint, left, top, radii[vert], stroke, prevX,prevY,currX,currY,nextX,nextY);
289
        }
290
      else
291
        {
292
        drawCurrCurveV(canvas, paint, left, top, radii[vert], stroke, prevX,prevY,currX,currY,nextX,nextY,prevA,currA);
293
        }
294
295
      prevX = currX;
296
      prevY = currY;
297
      currX = nextX;
298
      currY = nextY;
299
300
      prevA = currA;
301
      currA = getAngle(angles, vert==numVertices-1 ? 0 : vert+1);
302
303
      if( 2*(vert+2)+1 < length )
304
        {
305
        nextX = vertices[2*(vert+2)  ];
306
        nextY = vertices[2*(vert+2)+1];
307
        }
308
      else
309
        {
310
        nextX = vertices[0];
311
        nextY = vertices[1];
312
        }
313
      }
314
    }
315
  }