如何使用无序CGPoints绘制特定的CGPath
考虑这个ASCII图:
A _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ D
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
B C
点A,B,C和D是NSMutableArray
中已知的CGPoints
,并用于创建一个填充的CGPath
。 现在考虑这张图:
A _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ D
| |
| |
| |
| |
| H _ _ _ I |
| | | |
| | | |
| F _ _ _| | |
| | G | |
| | |_ _ _ K |
| | J | |
| | | |
|_ _ _ _| _ _ _ _ _ _ _ _ |_ _ _|
B E L C
CGPoints
E,F,G,H,I,J,K和L是已知的,并已被附加到NSMutableArray
的末尾。
问题
如何重新排列数组中的所有点以创建一个如下图所示的CGPath
?
A _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ D
| |
| |
| |
| |
| H _ _ _ I |
| | | |
| | | |
| F _ _ _| | |
| | G | |
| | |_ _ _ K |
| | J | |
| | | |
|_ _ _ _| |_ _ _|
B E L C
目前我没有创建CGPath
麻烦 - 如果我知道CGpoints
的顺序 - 通过遍历它们:
CGPoint firstPoint = [[points objectAtIndex:0] CGPointValue];
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, firstPoint.x, firstPoint.y);
for (int i = 0; i < [points count]; i++)
{
CGPathAddLineToPoint(path, NULL, [[points objectAtIndex:i] CGPointValue].x, [[points objectAtIndex:i] CGPointValue].y);
}
CGPathCloseSubpath(path);
...但是这假设应该从数组i
中的每个点绘制一条线到下面的点i + 1
。 在上图中,线必须从A → B
, B → E
, E → F
K → L
, L → C
, C → D
绘制。 如果E不在B之后,C不在数组L之后(它们不会),那么这显然不会正确绘制。
更多信息
CGPoints
应该在它们之前和之后与CGPoint
共享一个x
或y
坐标。 其他可能的布局
A _ _ _ _ _ _ _ K P _ _ _ D
| | | |
| | | |
| | N _ _ _| |
| | | O |
| |_ _ _| |
| L M |
| |
| F _ _ _ G |
| | | |
| | |_ _ _ I |
| | H | |
| | | |
|_ _ _ _ _ _ _| |_ _ _|
B E J C
A _ _ _ _ _ _ _ _ _ _ M
| |
| |
| |_ _ _ _ _ _ O
| N |
| H _ _ _ I |
| | | |
| | | |
| F _ _ _| | |
| | G | |
| | |_ _ _ K |
| | J | |
| | | |
|_ _ _ _| |_ _ _|
B E L C
我认为这可能会做到。 我用几组数字对它进行了测试,它似乎工作。 基本上,我从索引0开始(任何起点应该工作),将其添加到arrangePoints数组,然后查找具有相同y值的最近点 - 该点将添加到排列好的点并从原始随机点中删除阵列。 然后,我在x方向上做同样的事情并重复,直到randomPoints数组中只剩下一个点,并将其添加到arrangePoints的末尾。
-(void)arrangePoints:(NSMutableArray *) randomPoints {
NSMutableArray *arrangedPoints = [NSMutableArray array];
[arrangedPoints addObject:[randomPoints objectAtIndex:0]];
[randomPoints removeObjectAtIndex:0];
while (randomPoints.count > 1) {
//Look for the closest point that has the same y value
int yValueOfknownPoint = [[arrangedPoints lastObject] CGPointValue].y;
int xValueOfknownPoint = [[arrangedPoints lastObject] CGPointValue].x;
NSIndexSet *indSet = [randomPoints indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
return yValueOfknownPoint == [obj CGPointValue].y;
}];
NSLog(@"%d",indSet.count);
if (indSet.count == 1) {
[arrangedPoints addObject:[randomPoints objectAtIndex:indSet.firstIndex]];
[randomPoints removeObjectAtIndex:indSet.firstIndex];
}else{
__block int min = 10000000;
__block int foundIndex;
[indSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
int posibleMin = fabs(xValueOfknownPoint - [[randomPoints objectAtIndex:idx]CGPointValue].x);
if (posibleMin < min) {
min = posibleMin;
foundIndex = idx;
}
}];
[arrangedPoints addObject:[randomPoints objectAtIndex:foundIndex]];
[randomPoints removeObjectAtIndex:foundIndex];
}
//Look for the closest point that has the same x value
xValueOfknownPoint = [[arrangedPoints lastObject] CGPointValue].x;
yValueOfknownPoint = [[arrangedPoints lastObject] CGPointValue].y;
indSet = [randomPoints indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
return xValueOfknownPoint == [obj CGPointValue].x;
}];
if (indSet.count == 1) {
[arrangedPoints addObject:[randomPoints objectAtIndex:indSet.firstIndex]];
[randomPoints removeObjectAtIndex:indSet.firstIndex];
}else{
__block int min = 10000000;
__block int foundIndex;
[indSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
int posibleMin = fabs(yValueOfknownPoint - [[randomPoints objectAtIndex:idx]CGPointValue].y);
if (posibleMin < min) {
min = posibleMin;
foundIndex = idx;
}
}];
[arrangedPoints addObject:[randomPoints objectAtIndex:foundIndex]];
[randomPoints removeObjectAtIndex:foundIndex];
}
}
[arrangedPoints addObject:randomPoints.lastObject];
NSLog(@"%@",arrangedPoints);
}
解决已知问题的一些补充点:
为了处理像N和G这样的等距点,我想我会保持点集合不同 - 而不是把每个东西放到一个数组中,我会保留原始的矩形,并且每个新的点集合都是分开的。 然后,当我构建路径时,我只会在自己的一组点或原始矩形内寻找点,而不是在其他任何点中寻找点。
为了解决提出的问题,增加双倍回报,我认为你必须确定一组点是否与一个边或一个角相交 - 我认为只有边角点才会出现这个问题。 您可以通过查看2个点落在原始矩形的2条不同线上(而不是在同一条线上)来检查角点。 然后你必须计算出缺少的点(上面最后一个例子中的一个假定点p),并查看原始矩形的哪个点也是相同的,然后从路径中删除该点。 我认为我的算法会正常工作。
这里有一种方法(伪代码),如果你感兴趣的是填充而不是笔画:
使用CGPathCreateMutable()
创建一个空的可变路径。
将原始的矩形图形添加到可变路径作为闭环。
逐个添加每个不规则图形到可变路径,作为一个闭环。
使用函数CGContextEOFillPath()
使用偶数填充规则填充被侵蚀的图形。
奇数填充规则在Quartz 2D Programming Guide
填充路径一节中介绍。
您可能也对此感兴趣
好吧,这可能看起来是一个非常复杂的算法(它远非最佳),但我会这样来处理它。
1. Find the point(s) with lowest X-value
2. Of those points find point P (using a loop) such that:
- P has a nabour N with the same X-value
- There exists no other point that vertically lies between P and its nabour N with the same Y value
(if no P exists with a nabour, the algorithm has ended, after joining P with its horizontally aligned point)
3. If there exists a point with the same X value as P (horizontally aligned), join that point and P with a line.
4. Now join point P with its nabour N
5. Find all points with the same X-value as N (horizontally aligned)
6. Goto 2
我希望它有效(还没有测试过)。
链接地址: http://www.djcxy.com/p/61823.html