Project

General

Profile

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

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

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.helpers;
21

    
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
  }
(3-3/11)