動態計算選中路徑,畫虛線框
阿新 • • 發佈:2019-01-23
我大哥說過,【沒有一種演算法是脫離實際問題而存在的。】
於是,當我遇到這個問題時候,我知道計算機理論上學的演算法都不能解決這個問題,我需要靈活運用。
例1
例2
專案中遇到這麼一個棘手的問題,要根據網路獲取的實時資料,把同一工序的狀態畫虛線框起來。
也不算是個很困難的問題,但是還是有一定的複雜度,經過一晚上思考,找到了一種比較好的演算法。
相信看完了圖片,大家發現了這個演算法的核心所在——就是每一行上面的4個輔助點。所包含的範圍起始分解一下就是n個矩形,然後根據矩形的4個角的點,連線即可。
所以,步驟就有了:
第一步:根據給定的起始圓圈和終止圓圈,找出所有選中的圓圈 放在selectedArr中
第二部:便利selectedArr,找出每一行的最左邊和最右邊的圓圈,分別放進leftProviews和rightProviews陣列中,為了取四角的座標值用
第三部:左邊的座標依次連線,右邊的座標依次連線,最有把最頂上和最底下兩個座標相連,一個虛線框就出來了。
【圓圈是ProcessView:UIButton】
為了方便我判斷行列,我繼承UIButton,給button添加了row和count兩個屬性
@row:行
@count:順序(這裡之所以不用cow列來表示,是因為隔行的圓圈順序排列是相反的,有的從左到右,有的從右到左)
/**
給定起始圓圈和結束圓圈 找圓圈陣列,找矩形,最後畫線框
@param start 開始圓圈
@param end 結束圓圈
*/
-(void)DrawDashLineRectStart:(ProcessView *)start end:(ProcessView *)end{
// 畫之前先清除之前的虛線
NSArray *sublayers = [NSArray arrayWithArray:self.contentView.layer.sublayers];
for (CALayer *ly in sublayers) {
if ([ly isKindOfClass:[XLShapeLayer class]]) {
XLShapeLayer *xlL = (XLShapeLayer *)ly;
if (xlL.tag == 999) {
[xlL removeFromSuperlayer];
}
}
}
NSMutableArray *selectedArr = [NSMutableArray new ];
for (short i = start.row; i<=end.row; i++) {
for (short j = 0; j<6; j++) {
if(i == start.row && j < start.count) continue;
if (i == end.row && j > end.count) break;
ProcessView *pro = (ProcessView *)[self.contentView viewWithTag:60+(i*6+j)];
[selectedArr addObject:pro];
//DLog(@"pro:%ld %ld", pro.row, pro.count);
//DLog(@"%@",pro.titleLabel.text);
}
}
// 列印該被選中的陣列
//DLog(@"Pro:%@",selectedArr);
// 分出左右陣列 左陣列存放左邊的點依賴的圓圈 右陣列同理。
NSMutableArray *leftPros = [NSMutableArray new];
NSMutableArray *rightPros = [NSMutableArray new];
for (ProcessView *pro in selectedArr) {
if (end.row > start.row) {
if (pro.row%2==0) {
if ((pro.count==0) || pro==start) {
[leftPros addObject:pro];
}
if (pro.count == 5 || pro==end) {
[rightPros addObject:pro];
}
}
if (pro.row%2==1) {
if ((pro.count==0 || pro == start)) {
[rightPros addObject:pro];
}
if (pro.count==5 || pro==end) {
[leftPros addObject:pro];
}
}
}else{
if (end.row%2==0) {
[leftPros addObject:start];
[rightPros addObject:end];
}else{
[leftPros addObject:end];
[rightPros addObject:start];
}
break;
}
}
/* // 左右陣列資訊列印
for (short i =0; i<leftPros.count; i++) {
ProcessView *p = leftPros[i];
DLog(@"L:%@",p.titleLabel.text);
}
for (short i =0; i<rightPros.count; i++) {
ProcessView *p = rightPros[i];
DLog(@"R:%@",p.titleLabel.text);
}
*/
// 根據左右陣列,找到左邊的所有點 和右邊的所有點 然後依次相連
// spc是實際的點與圓圈frame的偏移量,因為虛線要離開圓圈一段距離
NSMutableArray *leftPoints = [NSMutableArray new];
NSMutableArray *rightPoints = [NSMutableArray new];
CGAffineTransform lastTransform;
for (ProcessView *pro in leftPros) {
lastTransform = pro.layer.affineTransform;
pro.layer.affineTransform = pro->affineTransform;
CGPoint start = CGPointMake(pro.frame.origin.x-spc/2., pro.frame.origin.y-spc/2.);
CGPoint end = CGPointMake(start.x, CGRectGetMaxY(pro.frame)+spc/2.);
[leftPoints addObject:NSStringFromCGPoint(start)];
[leftPoints addObject:NSStringFromCGPoint(end)];
pro.layer.affineTransform = lastTransform;
}
for (ProcessView *pro in rightPros) {
lastTransform = pro.layer.affineTransform;
pro.layer.affineTransform = pro->affineTransform;
CGPoint start = CGPointMake(CGRectGetMaxX(pro.frame)+spc/2., pro.frame.origin.y-spc/2.);
CGPoint end = CGPointMake(start.x, CGRectGetMaxY(pro.frame)+spc/2.);
[rightPoints addObject:NSStringFromCGPoint(start)];
[rightPoints addObject:NSStringFromCGPoint(end)];
pro.layer.affineTransform = lastTransform;
}
//左邊的點連線
for (short i=leftPoints.count-1; i>0; i--) {
CGPoint start = CGPointFromString(leftPoints[i]);
CGPoint end = CGPointFromString(leftPoints[i-1]);
[self drawDashLineStart:start end:end];
}
//右邊的點連線
for (short i=rightPoints.count-1; i>0; i--) {
CGPoint start = CGPointFromString(rightPoints[i]);
CGPoint end = CGPointFromString(rightPoints[i-1]);
[self drawDashLineStart:start end:end];
}
// 頂上和地下的點連線
CGPoint topL = CGPointFromString(leftPoints[0]);
CGPoint topR = CGPointFromString(rightPoints[0]);
CGPoint btmL = CGPointFromString([leftPoints lastObject]);
CGPoint btmR = CGPointFromString([rightPoints lastObject]);
[self drawDashLineStart:topL end:topR];
[self drawDashLineStart:btmL end:btmR];
}
畫虛線的方法,用CAShapeLayer即可
/**
給定起點 重點畫虛線
@param start 起點座標
@param end 終點座標
*/
- (void)drawDashLineStart:(CGPoint)start end:(CGPoint)end{
//NSLog(@"%@",NSStringFromCGRect(lineView.frame));
XLShapeLayer *shapeLayer = [XLShapeLayer layer];
shapeLayer.tag = 999;
[shapeLayer setBounds:self.contentView.bounds];
[shapeLayer setPosition:CGPointMake(CGRectGetWidth(self.contentView.frame)/2.f, CGRectGetHeight(self.contentView.frame)/2.f)];
[shapeLayer setFillColor:[[UIColor clearColor] CGColor]];
// 設定虛線顏色為blackColor [shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[shapeLayer setStrokeColor:KLIGHTGRAYCOLOR.CGColor];
// 3.0f設定虛線的寬度 [shapeLayer setLineWidth:1.0f];
[shapeLayer setLineJoin:kCALineJoinRound];
// 3=線的寬度 1=每條線的間距 [shapeLayer setLineDashPattern:
[shapeLayer setLineDashPattern:[NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:3],nil]];
// Setup the path CGMutablePathRef path = CGPathCreateMutable();
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, start.x, start.y);
CGPathAddLineToPoint(path, NULL, end.x,end.y);
[shapeLayer setPath:path];
CGPathRelease(path);
[self.contentView.layer addSublayer:shapeLayer];
}