Revision 1ebc4767
Added by Leszek Koltunski about 5 years ago
| src/main/java/org/distorted/objects/Cubit.java | ||
|---|---|---|
| 150 | 150 |
} |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 154 |
|
|
| 155 |
Static3D getOrigPosition() |
|
| 156 |
{
|
|
| 157 |
return mOrigPosition; |
|
| 158 |
} |
|
| 159 |
|
|
| 153 | 160 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 154 | 161 |
|
| 155 | 162 |
int computeAssociation() |
| ... | ... | |
| 185 | 192 |
return mQuatIndex; |
| 186 | 193 |
} |
| 187 | 194 |
|
| 188 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 189 |
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different |
|
| 190 |
// then if it were rotated by quaternion 'quat'. |
|
| 191 |
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two |
|
| 192 |
// middle squares get interchanged. No visible difference! |
|
| 193 |
// |
|
| 194 |
// So: this is true iff the cubit |
|
| 195 |
// a) is a corner or edge and the quaternions are the same |
|
| 196 |
// b) is inside one of the faces and after rotations by both quats it ends up on the same face. |
|
| 197 |
|
|
| 198 |
boolean thereIsNoVisibleDifference(int quatIndex) |
|
| 199 |
{
|
|
| 200 |
if ( mQuatIndex == quatIndex ) return true; |
|
| 201 |
|
|
| 202 |
int belongsToHowManyFaces = 0; |
|
| 203 |
int size = mParent.getSize()-1; |
|
| 204 |
float row; |
|
| 205 |
final float MAX_ERROR = 0.01f; |
|
| 206 |
|
|
| 207 |
for(int i=0; i<mNumAxis; i++) |
|
| 208 |
{
|
|
| 209 |
row = mRotationRow[i]; |
|
| 210 |
if( (row <MAX_ERROR && row >-MAX_ERROR) || |
|
| 211 |
(row-size<MAX_ERROR && row-size>-MAX_ERROR) ) belongsToHowManyFaces++; |
|
| 212 |
} |
|
| 213 |
|
|
| 214 |
switch(belongsToHowManyFaces) |
|
| 215 |
{
|
|
| 216 |
case 0 : return true ; // 'inside' cubit that does not lie on any face |
|
| 217 |
case 1 : // cubit that lies inside one of the faces |
|
| 218 |
float cubitCenterX = mOrigPosition.get0(); |
|
| 219 |
float cubitCenterY = mOrigPosition.get1(); |
|
| 220 |
float cubitCenterZ = mOrigPosition.get2(); |
|
| 221 |
|
|
| 222 |
Static4D quat1 = mParent.QUATS[quatIndex]; |
|
| 223 |
Static4D quat2 = mParent.QUATS[mQuatIndex]; |
|
| 224 |
|
|
| 225 |
Static4D cubitCenter = new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0); |
|
| 226 |
Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 ); |
|
| 227 |
Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 ); |
|
| 228 |
|
|
| 229 |
float row1, row2, row3, row4; |
|
| 230 |
float ax,ay,az; |
|
| 231 |
Static3D axis; |
|
| 232 |
float x1 = rotated1.get0(); |
|
| 233 |
float y1 = rotated1.get1(); |
|
| 234 |
float z1 = rotated1.get2(); |
|
| 235 |
float x2 = rotated2.get0(); |
|
| 236 |
float y2 = rotated2.get1(); |
|
| 237 |
float z2 = rotated2.get2(); |
|
| 238 |
|
|
| 239 |
for(int i=0; i<mNumAxis; i++) |
|
| 240 |
{
|
|
| 241 |
axis = mParent.ROTATION_AXIS[i]; |
|
| 242 |
ax = axis.get0(); |
|
| 243 |
ay = axis.get1(); |
|
| 244 |
az = axis.get2(); |
|
| 245 |
|
|
| 246 |
row1 = ((x1*ax + y1*ay + z1*az) - mParent.mStart) / mParent.mStep; |
|
| 247 |
row2 = ((x2*ax + y2*ay + z2*az) - mParent.mStart) / mParent.mStep; |
|
| 248 |
row3 = row1 - size; |
|
| 249 |
row4 = row2 - size; |
|
| 250 |
|
|
| 251 |
if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) || |
|
| 252 |
(row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR) ) |
|
| 253 |
{
|
|
| 254 |
return true; |
|
| 255 |
} |
|
| 256 |
} |
|
| 257 |
return false; |
|
| 258 |
|
|
| 259 |
default: return false; // edge or corner |
|
| 260 |
} |
|
| 261 |
} |
|
| 262 |
|
|
| 263 | 195 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 264 | 196 |
|
| 265 | 197 |
int removeRotationNow(Static4D quat) |
| src/main/java/org/distorted/objects/RubikCube.java | ||
|---|---|---|
| 35 | 35 |
import org.distorted.library.type.Static1D; |
| 36 | 36 |
import org.distorted.library.type.Static3D; |
| 37 | 37 |
import org.distorted.library.type.Static4D; |
| 38 |
import org.distorted.main.RubikSurfaceView; |
|
| 38 | 39 |
|
| 39 | 40 |
import java.util.Random; |
| 40 | 41 |
|
| ... | ... | |
| 393 | 394 |
return 0; |
| 394 | 395 |
} |
| 395 | 396 |
|
| 397 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 398 |
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different |
|
| 399 |
// then if it were rotated by quaternion 'quat'. |
|
| 400 |
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two |
|
| 401 |
// middle squares get interchanged. No visible difference! |
|
| 402 |
// |
|
| 403 |
// So: this is true iff the cubit |
|
| 404 |
// a) is a corner or edge and the quaternions are the same |
|
| 405 |
// b) is inside one of the faces and after rotations by both quats it ends up on the same face. |
|
| 406 |
|
|
| 407 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex) |
|
| 408 |
{
|
|
| 409 |
if ( cubit.mQuatIndex == quatIndex ) return true; |
|
| 410 |
|
|
| 411 |
int belongsToHowManyFaces = 0; |
|
| 412 |
int size = getSize()-1; |
|
| 413 |
float row; |
|
| 414 |
final float MAX_ERROR = 0.01f; |
|
| 415 |
|
|
| 416 |
for(int i=0; i<NUM_AXIS; i++) |
|
| 417 |
{
|
|
| 418 |
row = cubit.mRotationRow[i]; |
|
| 419 |
if( (row <MAX_ERROR && row >-MAX_ERROR) || |
|
| 420 |
(row-size<MAX_ERROR && row-size>-MAX_ERROR) ) belongsToHowManyFaces++; |
|
| 421 |
} |
|
| 422 |
|
|
| 423 |
switch(belongsToHowManyFaces) |
|
| 424 |
{
|
|
| 425 |
case 0 : return true ; // 'inside' cubit that does not lie on any face |
|
| 426 |
case 1 : // cubit that lies inside one of the faces |
|
| 427 |
Static3D orig = cubit.getOrigPosition(); |
|
| 428 |
Static4D quat1 = QUATS[quatIndex]; |
|
| 429 |
Static4D quat2 = QUATS[cubit.mQuatIndex]; |
|
| 430 |
|
|
| 431 |
Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0); |
|
| 432 |
Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 ); |
|
| 433 |
Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 ); |
|
| 434 |
|
|
| 435 |
float row1, row2, row3, row4; |
|
| 436 |
float ax,ay,az; |
|
| 437 |
Static3D axis; |
|
| 438 |
float x1 = rotated1.get0(); |
|
| 439 |
float y1 = rotated1.get1(); |
|
| 440 |
float z1 = rotated1.get2(); |
|
| 441 |
float x2 = rotated2.get0(); |
|
| 442 |
float y2 = rotated2.get1(); |
|
| 443 |
float z2 = rotated2.get2(); |
|
| 444 |
|
|
| 445 |
for(int i=0; i<NUM_AXIS; i++) |
|
| 446 |
{
|
|
| 447 |
axis = ROTATION_AXIS[i]; |
|
| 448 |
ax = axis.get0(); |
|
| 449 |
ay = axis.get1(); |
|
| 450 |
az = axis.get2(); |
|
| 451 |
|
|
| 452 |
row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep; |
|
| 453 |
row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep; |
|
| 454 |
row3 = row1 - size; |
|
| 455 |
row4 = row2 - size; |
|
| 456 |
|
|
| 457 |
if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) || |
|
| 458 |
(row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR) ) |
|
| 459 |
{
|
|
| 460 |
return true; |
|
| 461 |
} |
|
| 462 |
} |
|
| 463 |
return false; |
|
| 464 |
|
|
| 465 |
default: return false; // edge or corner |
|
| 466 |
} |
|
| 467 |
} |
|
| 468 |
|
|
| 396 | 469 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 397 | 470 |
// order: Up --> Right --> Front --> Down --> Left --> Back |
| 398 | 471 |
// (because the first implemented Solver - the two-phase Cube3 one - expects such order) |
| src/main/java/org/distorted/objects/RubikDino.java | ||
|---|---|---|
| 441 | 441 |
} |
| 442 | 442 |
} |
| 443 | 443 |
|
| 444 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 445 |
// here it's simple - all cubits have to be rotated with the same quaretnion for the whole thing |
|
| 446 |
// to be solved. |
|
| 447 |
|
|
| 448 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex) |
|
| 449 |
{
|
|
| 450 |
return cubit.mQuatIndex == quatIndex; |
|
| 451 |
} |
|
| 452 |
|
|
| 444 | 453 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 445 | 454 |
// TODO (only needed for solvers - there are no Dino solvers ATM) |
| 446 | 455 |
|
| src/main/java/org/distorted/objects/RubikObject.java | ||
|---|---|---|
| 70 | 70 |
final Static4D[] QUATS; |
| 71 | 71 |
final int NUM_FACES; |
| 72 | 72 |
final int NUM_CUBIT_FACES; |
| 73 |
final int NUM_AXIS; |
|
| 73 | 74 |
|
| 74 | 75 |
private static float mInitScreenRatio,mObjectScreenRatio; |
| 75 | 76 |
|
| ... | ... | |
| 116 | 117 |
QUATS = getQuats(); |
| 117 | 118 |
NUM_CUBITS = mOrigPos.length; |
| 118 | 119 |
ROTATION_AXIS = getRotationAxis(); |
| 120 |
NUM_AXIS = ROTATION_AXIS.length; |
|
| 119 | 121 |
mObjectScreenRatio = getScreenRatio(); |
| 120 | 122 |
mInitScreenRatio = mObjectScreenRatio; |
| 121 | 123 |
NUM_FACES = getNumFaces(); |
| ... | ... | |
| 485 | 487 |
|
| 486 | 488 |
for(int i=1; i<NUM_CUBITS; i++) |
| 487 | 489 |
{
|
| 488 |
if( !mCubits[i].thereIsNoVisibleDifference(index) ) return false;
|
|
| 490 |
if( !thereIsNoVisibleDifference(mCubits[i], index) ) return false;
|
|
| 489 | 491 |
} |
| 490 | 492 |
|
| 491 | 493 |
return true; |
| ... | ... | |
| 701 | 703 |
abstract int getFaceColor(int cubit, int cubitface, int size); |
| 702 | 704 |
abstract float returnMultiplier(); |
| 703 | 705 |
abstract float[] getRowChances(); |
| 706 |
abstract boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex); |
|
| 704 | 707 |
|
| 705 | 708 |
public abstract Static3D[] getRotationAxis(); |
| 706 | 709 |
public abstract int getBasicAngle(); |
| src/main/java/org/distorted/objects/RubikPyraminx.java | ||
|---|---|---|
| 37 | 37 |
import org.distorted.library.type.Static1D; |
| 38 | 38 |
import org.distorted.library.type.Static3D; |
| 39 | 39 |
import org.distorted.library.type.Static4D; |
| 40 |
import org.distorted.main.RubikSurfaceView; |
|
| 40 | 41 |
|
| 41 | 42 |
import java.util.Random; |
| 42 | 43 |
|
| ... | ... | |
| 485 | 486 |
return 0; |
| 486 | 487 |
} |
| 487 | 488 |
|
| 489 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 490 |
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different |
|
| 491 |
// then if it were rotated by quaternion 'quat'. |
|
| 492 |
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two |
|
| 493 |
// middle squares get interchanged. No visible difference! |
|
| 494 |
// |
|
| 495 |
// So: this is true iff the cubit |
|
| 496 |
// a) is a corner or edge and the quaternions are the same |
|
| 497 |
// b) is inside one of the faces and after rotations by both quats it ends up on the same face. |
|
| 498 |
|
|
| 499 |
boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex) |
|
| 500 |
{
|
|
| 501 |
if ( cubit.mQuatIndex == quatIndex ) return true; |
|
| 502 |
|
|
| 503 |
int belongsToHowManyFaces = 0; |
|
| 504 |
int size = getSize()-1; |
|
| 505 |
float row; |
|
| 506 |
final float MAX_ERROR = 0.01f; |
|
| 507 |
|
|
| 508 |
for(int i=0; i<NUM_AXIS; i++) |
|
| 509 |
{
|
|
| 510 |
row = cubit.mRotationRow[i]; |
|
| 511 |
if( (row <MAX_ERROR && row >-MAX_ERROR) || |
|
| 512 |
(row-size<MAX_ERROR && row-size>-MAX_ERROR) ) belongsToHowManyFaces++; |
|
| 513 |
} |
|
| 514 |
|
|
| 515 |
switch(belongsToHowManyFaces) |
|
| 516 |
{
|
|
| 517 |
case 0 : return true ; // 'inside' cubit that does not lie on any face |
|
| 518 |
case 1 : // cubit that lies inside one of the faces |
|
| 519 |
Static3D orig = cubit.getOrigPosition(); |
|
| 520 |
Static4D quat1 = QUATS[quatIndex]; |
|
| 521 |
Static4D quat2 = QUATS[cubit.mQuatIndex]; |
|
| 522 |
|
|
| 523 |
Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0); |
|
| 524 |
Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 ); |
|
| 525 |
Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 ); |
|
| 526 |
|
|
| 527 |
float row1, row2, row3, row4; |
|
| 528 |
float ax,ay,az; |
|
| 529 |
Static3D axis; |
|
| 530 |
float x1 = rotated1.get0(); |
|
| 531 |
float y1 = rotated1.get1(); |
|
| 532 |
float z1 = rotated1.get2(); |
|
| 533 |
float x2 = rotated2.get0(); |
|
| 534 |
float y2 = rotated2.get1(); |
|
| 535 |
float z2 = rotated2.get2(); |
|
| 536 |
|
|
| 537 |
for(int i=0; i<NUM_AXIS; i++) |
|
| 538 |
{
|
|
| 539 |
axis = ROTATION_AXIS[i]; |
|
| 540 |
ax = axis.get0(); |
|
| 541 |
ay = axis.get1(); |
|
| 542 |
az = axis.get2(); |
|
| 543 |
|
|
| 544 |
row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep; |
|
| 545 |
row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep; |
|
| 546 |
row3 = row1 - size; |
|
| 547 |
row4 = row2 - size; |
|
| 548 |
|
|
| 549 |
if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) || |
|
| 550 |
(row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR) ) |
|
| 551 |
{
|
|
| 552 |
return true; |
|
| 553 |
} |
|
| 554 |
} |
|
| 555 |
return false; |
|
| 556 |
|
|
| 557 |
default: return false; // edge or corner |
|
| 558 |
} |
|
| 559 |
} |
|
| 560 |
|
|
| 488 | 561 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 489 | 562 |
// TODO (only needed for solvers - there are no Pyraminx solvers ATM) |
| 490 | 563 |
|
Also available in: Unified diff
Fix detecting if an Object is solved. Before, the generic Cubit.thereIsNoVisibleDifference(0 would not work correctly in case of the Dino.