opengl绘制固定宽度多边形圆角边框算法(历时周半,撰博文以志纪念)II

来源:互联网 发布:eclipse导入jre源码 编辑:程序博客网 时间:2024/06/10 13:08

BYLineII.h

////  BYLineII.h//  SuperBalance1.1////  Created by Bruce Yang on 7/26/11.//  Copyright 2011 Home. All rights reserved.//@protocol BYLineIIstruct 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