#import "Views.h" #import "Controller.h" @implementation Rubik - initAtPoint:(NSPoint)aPoint controller:(id)theCon { NSRect frame; int x, y, z, b1, b2, index; frame.origin = aPoint; frame.size.width = frame.size.height = DIMENSION; [super initWithFrame:frame]; [self setBoundsSize:NSMakeSize(4.0, 4.0)]; [self setBoundsOrigin:NSMakePoint(-2.0, -2.0)]; con = theCon; for(x=-1; x<=1; x+=2){ for(y=-1; y<=1; y+=2){ for(z=-1; z<=1; z+=2){ int index = 4*(x==-1 ? 0 : 1)+ 2*(y==-1 ? 0 : 1)+ (z==-1 ? 0 : 1); vertices[index].x = x; vertices[index].y = y; vertices[index].z = z; vertices[index].index = index; colors[index] = [NSColor colorWithDeviceRed:(x==-1 ? 0.0 : 1.0) green:(y==-1 ? 0.0 : 1.0) blue:(z==-1 ? 0.0 : 1.0) alpha:1.0]; [colors[index] retain]; } } } index = 0; for(b1=0; b1<=2; b1++){ for(b2=b1+1; b2<=2; b2++){ /* counterclockwise */ int reorient = index + 1-(index/2)%2; int temp; face[index][0] = 0; face[index][1] = face[index][0]+(1<x, y = v->y, z = v->z; switch(rv){ case ROT_X: v->y = y * cosTheta - z * sinTheta; v->z = y * sinTheta + z * cosTheta; break; case ROT_Y: v->x = x * cosTheta - z * sinTheta; v->z = x * sinTheta + z * cosTheta; break; case ROT_Z: v->x = x * cosTheta - y * sinTheta; v->y = x * sinTheta + y * cosTheta; } } return self; } - recomputeGeometry { int index, findex, upper; if(rcur!=rprev){ [self rotate:active aboutUnitVector:rcur angle:-angle]; memcpy(indexed, active, 8*sizeof(Vertex)); rprev = rcur; /* { double dx = indexed[0].x-indexed[1].x, dy = indexed[0].y-indexed[1].y, dz = indexed[0].z-indexed[1].z; NSLog(@"%le\n", dx*dx+dy*dy+dz*dz); } */ } memcpy(active, indexed, 8*sizeof(Vertex)); [self rotate:active aboutUnitVector:rcur angle:angle]; memcpy(sorted, active, 8*sizeof(Vertex)); for(upper=6; upper>=0; upper--){ for(index=0; index<=upper; index++){ if(sorted[index].y>sorted[index+1].y){ Vertex current; current = sorted[index]; sorted[index] = sorted[index+1]; sorted[index+1] = current; } } } index = 0; for(index=1; index<8; index++){ double delta = sorted[index].y-sorted[index-1].y; if(delta>DELTA){ break; } } if(index==1){ int v = sorted[0].index; vis = VIS_F_3; findex = 0; for(index=0; index<6; index++){ if(face[index][0]==v || face[index][1]==v || face[index][2]==v || face[index][3]==v){ visface[findex++] = index; } } } else if(index==2){ int v1 = sorted[0].index, v2 = sorted[1].index; vis = VIS_F_2; findex = 0; for(index=0; index<6; index++){ if((face[index][0]==v1 || face[index][1]==v1 || face[index][2]==v1 || face[index][3]==v1) && (face[index][0]==v2 || face[index][1]==v2 || face[index][2]==v2 || face[index][3]==v2)){ visface[findex++] = index; } } } else { int v1 = sorted[0].index, v2 = sorted[1].index, v3 = sorted[2].index, v4 = sorted[3].index; vis = VIS_F_1; findex = 0; for(index=0; index<6; index++){ if((face[index][0]==v1 || face[index][1]==v1 || face[index][2]==v1 || face[index][3]==v1) && (face[index][0]==v2 || face[index][1]==v2 || face[index][2]==v2 || face[index][3]==v2) && (face[index][0]==v3 || face[index][1]==v3 || face[index][2]==v3 || face[index][3]==v3) && (face[index][0]==v4 || face[index][1]==v4 || face[index][2]==v4 || face[index][3]==v4)){ visface[findex++] = index; } } } [self setNeedsDisplay:YES]; return self; } - angle:(id)sender { angle = [sender doubleValue]; rcur = [sender tag]; [self recomputeGeometry]; return self; } - (BOOL)solved { int f, row, col; for(f=0; f<6; f++){ for(row=0; row<3; row++){ for(col=0; col<3; col++){ if(data[f][row][col]!=data[f][1][1]){ return NO; } } } } return YES; } - (void)drawRect:(NSRect)aRect { NSRect bounds = [self bounds]; int findex; [colors[0] set]; PSrectfill(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); PSsetlinewidth(4.0/(float)DIMENSION); for(findex=0; findex