BYLineII.h
//
// BYLineII.h
// SuperBalance1.1
//
// Created by Bruce Yang on 7/26/11.
// Copyright 2011 Home. All rights reserved.
//
@protocol BYLineII
struct BYLine {
float k;
float b;
BOOL kExists;
float extraX;
};
typedef struct BYLine BYLine;
@end
GenericBase.mm
//
// GenericBase.mm
// SuperBalance1.1
//
// Created by Bruce Yang on 7/26/11.
// Copyright 2011 Home. All rights reserved.
//
#import "GenericBase.h"
@implementation GenericBase
+ (BYLine) getLine:(CGPoint)p1 anotherPoint:(CGPoint)p2 {
BYLine line;
if((p1.x - p2.x) != 0) {
float k = (p1.y - p2.y)/(p1.x - p2.x);
float b = (p1.y - p1.x * k);
line.kExists = true;
line.k = k;
line.b = b;
} else {
line.kExists = false;
line.extraX = p1.x;
}
return line;
}
+ (BYLine) getLine:(CGPoint)point kParam:(float)aK {
BYLine l;
l.k = aK;
l.b = point.y - aK*point.x;
return l;
}
+ (float) get2PointsDistance:(CGPoint)p0 anotherPoint:(CGPoint)p1 {
float distance = (float)sqrt(pow(p0.y - p1.y, 2) + pow(p0.x - p1.x, 2));
return distance;
}
+ (CGPoint) getCrossPoint:(BYLine)l1 lineParam:(BYLine)l2 {
float x, y;
if(l1.kExists && l2.kExists) {
x = (l2.b - l1.b) / (l1.k - l2.k);
y = l1.k * x + l1.b;
} else if(!l1.kExists && l2.kExists) {
x = l1.extraX;
y = l2.k * x + l2.b;
} else if(l1.kExists && !l2.kExists) {
x = l2.extraX;
y = l1.k * x + l1.b;
} else {
x = 0.0f;
y = 0.0f;
}
return ccp(x, y);
}
+ (CGPoint) getProjectivePoint:(CGPoint)p lineParam:(BYLine)l {
CGPoint target;
if(l.kExists) {
if(l.k != 0) {
BYLine newLine;
// 难道是因为少写了这个??果然是因为这个!!
// 足见一个良好的数据类型是多么的重要,如果一开始就是用类来完成BYLine结构体的功能的话,那将会大大降低出错的机率!!
newLine.kExists = true;
newLine.k = -1/l.k;
newLine.b = p.y -(-1/l.k)*p.x;
target = [GenericBase getCrossPoint:l lineParam:newLine];
} else {
target = ccp(p.x, l.b);
}
} else {
target = ccp(l.extraX, p.y);
}
return target;
}
+ (float) getRadian:(CGPoint)p1 secondPoint:(CGPoint)p2 thirdPoint:(CGPoint)p3 {
float l31, l12, l23, angle;
l31 = BORDER_WIDTH;
l12 = BORDER_WIDTH;
l23 = [GenericBase get2PointsDistance:p2 anotherPoint:p3];
float cosineValue = (l31*l31 + l12*l12 - l23*l23)/(2*l31*l12);
angle = (float)acos(cosineValue);
return angle;
}
+ (float) getB1:(float)k bParam:(float)b {
float result = (float) b + BORDER_WIDTH*(float)sqrt(k*k + 1);
return result;
}
+ (float) getB2:(float)k bParam:(float)b {
float result = (float) b - BORDER_WIDTH*(float)sqrt(k*k + 1);
return result;
}
+ (CGPoint*) getCircleCenter:(BYLine)l1 lineParam:(BYLine)l2 {
CGPoint *dest = new CGPoint[4];
BYLine l1_1, l1_2, l2_1, l2_2;
if(l1.kExists && l2.kExists) {
l1_1.kExists = true;
l1_1.k = l1.k;
l1_1.b = [GenericBase getB1:l1.k bParam:l1.b];
l1_2.kExists = true;
l1_2.k = l1.k;
l1_2.b = [GenericBase getB2:l1.k bParam:l1.b];
l2_1.kExists = true;
l2_1.k = l2.k;
l2_1.b = [GenericBase getB1:l2.k bParam:l2.b];
l2_2.kExists = true;
l2_2.k = l2.k;
l2_2.b = [GenericBase getB2:l2.k bParam:l2.b];
} else if(!l1.kExists && l2.kExists) {
l1_1.kExists = false;
l1_1.extraX = l1.extraX + BORDER_WIDTH;
l1_2.kExists = false;
l1_2.extraX = l1.extraX - BORDER_WIDTH;
l2_1.kExists = true;
l2_1.k = l2.k;
l2_1.b = [GenericBase getB1:l2.k bParam:l2.b];
l2_2.kExists = true;
l2_2.k = l2.k;
l2_2.b = [GenericBase getB2:l2.k bParam:l2.b];
} else if(l1.kExists && !l2.kExists) {
l1_1.kExists = true;
l1_1.k = l1.k;
l1_1.b = [GenericBase getB1:l1.k bParam:l1.b];
l1_2.kExists = true;
l1_2.k = l1.k;
l1_2.b = [GenericBase getB2:l1.k bParam:l1.b];
l2_1.kExists = false;
l2_1.extraX = l2.extraX + BORDER_WIDTH;
l2_2.kExists = false;
l2_2.extraX = l2.extraX - BORDER_WIDTH;
} else {
NSLog(@"It's no possible!");
}
dest[0] = [GenericBase getCrossPoint:l1_1 lineParam:l2_1];
dest[1] = [GenericBase getCrossPoint:l1_1 lineParam:l2_2];
dest[2] = [GenericBase getCrossPoint:l1_2 lineParam:l2_1];
dest[3] = [GenericBase getCrossPoint:l1_2 lineParam:l2_2];
return dest;
}
+ (CGPoint) getNearestPoint:(CGPoint*)points lineParam:(BYLine)line {
float minDistance = 0;
int minIndex = 0;
if(line.kExists) {
for(int i = 0; i < 4; i ++) {
CGPoint p = points[i];
float d = (float)(abs(line.k*p.x-p.y+line.b)/sqrt(pow(line.k,2)+1));
if(i == 0) {
minDistance = d;
}
if(d < minDistance) {
minDistance = d;
minIndex = i;
}
}
} else {
for(int i = 0; i < 4; i ++) {
CGPoint p = points[i];
float d = abs(p.x - line.extraX);
if(i == 0) {
minDistance = d;
}
if(d < minDistance) {
minDistance = d;
minIndex = i;
}
}
}
CGPoint dest = points[minIndex];
delete points;
return dest;
}
+ (CGPoint*) genGroupPoints:(CGPoint)pCircle pointParam1:(CGPoint)pProj1 pointParam2:(CGPoint)pProj2 {
CGPoint *target = new CGPoint[11];
float radian = [GenericBase getRadian:pCircle secondPoint:pProj1 thirdPoint:pProj2];
float deltaRadian = radian / 6;
float startRadian;
if((pProj1.y == pCircle.y) && (pProj1.x > pCircle.x)) {
startRadian = 0;
} else if((pProj1.y > pCircle.y) && (pProj1.x == pCircle.x)) {
startRadian = PI_ROUGH / 2;
} else if((pProj1.y == pCircle.y) && (pProj1.x < pCircle.x)) {
startRadian = PI_ROUGH;
} else if((pProj1.y < pCircle.y) && (pProj1.x == pCircle.x)) {
startRadian = PI_ROUGH * 3 / 2;
} else if((pProj1.y > pCircle.y) && (pProj1.x > pCircle.x)) {
startRadian = (float)atan(abs((pProj1.y - pCircle.y)/(pProj1.x - pCircle.x)));
} else if((pProj1.y > pCircle.y) && (pProj1.x < pCircle.x)) {
startRadian = (float)(PI_ROUGH - atan(abs((pProj1.y - pCircle.y)/(pProj1.x - pCircle.x))));
} else if((pProj1.y < pCircle.y) && (pProj1.x < pCircle.x)) {
startRadian = (float)(PI_ROUGH + atan(abs((pProj1.y - pCircle.y)/(pProj1.x - pCircle.x))));
} else {
startRadian = (float)(2*PI_ROUGH - atan(abs((pProj1.y - pCircle.y)/(pProj1.x - pCircle.x))));
}
target[1] = pCircle;
target[4] = pCircle;
target[7] = pCircle;
target[10] = pCircle;
for(int i = 0; i < 11; i ++) {
if(i==1 || i==4 || i==7 || i==10) {
continue;
} else {
target[i].x = target[1].x + (float)(BORDER_WIDTH * cos(startRadian));
target[i].y = target[1].y + (float)(BORDER_WIDTH * sin(startRadian));
startRadian -= deltaRadian;
}
}
if(DEBUG_MODE) {
}
return target;
}
@end
PointsGeneratorGeneric.mm
//
// PointsGeneratorGeneric.mm
// SuperBalance1.1
//
// Created Bruce Yang on 7/26/11.
// Copyright 2011 Home. All rights reserved.
//
#import "PointsGeneratorGeneric.h"
@implementation PointsGeneratorGeneric
+ (CGPoint*) genPolygonPoints:(CGPoint*)p pointsCount:(int)inPCount {
int outPCount = inPCount*11 + 2;
CGPoint *target = new CGPoint[outPCount];
int targetCurrentIndex = 0;
CGPoint p0, p1, p2;
for(int i = 0; i < inPCount; i ++) {
p0 = p[i];
p1 = (i-1 == -1) ? p[inPCount-1] : p[i-1];
p2 = (i+1 < inPCount) ? p[i+1] : p[0];
CGPoint *pGroup = [PointsGeneratorGeneric handleUnit:p0 secondPoint:p1 thirdPoint:p2];
for(int j = 0; j < 11; j ++) {
target[targetCurrentIndex + j] = pGroup[j];
}
delete pGroup;
targetCurrentIndex += 11;
}
target[outPCount-2] = target[0];
target[outPCount-1] = target[1];
return target;
}
+ (CGPoint*) handleUnit:(CGPoint)p0 secondPoint:(CGPoint)p1 thirdPoint:(CGPoint)p2 {
BYLine l_p0_p1 = [GenericBase getLine:p0 anotherPoint:p1];
BYLine l_p0_p2 = [GenericBase getLine:p0 anotherPoint:p2];
CGPoint *circleCenters = [GenericBase getCircleCenter:l_p0_p1 lineParam:l_p0_p2];
BYLine l_p1_p2 = [GenericBase getLine:p1 anotherPoint:p2];
CGPoint circleCenter = [GenericBase getNearestPoint:circleCenters lineParam:l_p1_p2];
CGPoint projectivePoint1 = [GenericBase getProjectivePoint:circleCenter lineParam:l_p0_p1];
CGPoint projectivePoint2 = [GenericBase getProjectivePoint:circleCenter lineParam:l_p0_p2];
CGPoint *pGroup = [GenericBase genGroupPoints:circleCenter pointParam1:projectivePoint1 pointParam2:projectivePoint2];
return pGroup;
}
@end